This is an automated email from the ASF dual-hosted git repository.

tbonelee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new 8a2b306bbc [ZEPPELIN-6463] Close the package.json reader in 
HeliumBundleFactory with try-with-resources
8a2b306bbc is described below

commit 8a2b306bbcc26d1cffa7737d304f72dbc1924944
Author: dae won <[email protected]>
AuthorDate: Thu Aug 6 11:10:23 2026 +0900

    [ZEPPELIN-6463] Close the package.json reader in HeliumBundleFactory with 
try-with-resources
    
    ### What is this PR for?
    
    `HeliumBundleFactory.downloadPackage()` stages a Helium package into its 
bundle directory, either by copying a local directory or by unpacking an npm 
tarball, and then reads the `package.json` it finds there to pull out the 
`dependencies` and `main` entries:
    
    ```java
    JsonReader reader = new JsonReader(new FileReader(existingPackageJson));
    Map<String, Object> packageJson = gson.fromJson(reader,
            new TypeToken<Map<String, Object>>(){}.getType());
    ```
    
    The reader is never closed. There is no `close()`, no `finally` and no 
try-with-resources, and Gson does not close a reader handed to it. Ownership 
stays with the caller.
    
    The descriptor is therefore released only once the garbage collector 
reclaims the `FileReader`, because `FileInputStream` registers itself for 
cleanup. So this is not an unbounded leak, but the release is not 
deterministic: the descriptor stays open for as long as the `FileReader` goes 
unreclaimed, which has nothing to do with the point where the parse finishes 
and the reader stops being useful. The same holds when parsing fails, since a 
malformed `package.json` makes Gson raise `Json [...]
    
    This PR wraps the reader in a try-with-resources so the descriptor is 
released as soon as parsing finishes. Only `JsonReader` is declared as a 
resource, since closing it closes the `FileReader` it wraps, which avoids a 
redundant second close. `packageJson` is declared ahead of the block so the 
parsed result remains available to the rest of the method. Parsing behaviour 
and the resulting bundle setup are unchanged, and no signatures or access 
modifiers change.
    
    ### What type of PR is it?
    Bug Fix
    
    ### Todos
    * [x] Close the `package.json` reader opened in `downloadPackage`
    
    ### What is the Jira issue?
    * https://issues.apache.org/jira/browse/ZEPPELIN-6463
    
    ### How should this be tested?
    
    ```bash
    ./mvnw package -pl zeppelin-server --am \
      -Dtest='HeliumBundleFactoryTest,HeliumTest,HeliumLocalRegistryTest' \
      -DfailIfNoTests=false
    ```
    
    `Tests run: 9, Failures: 0, Errors: 0, Skipped: 0`, and `zeppelin-server` 
builds.
    
    ### Screenshots (if appropriate)
    N/A
    
    ### Questions:
    * Does the license files need to update? No
    * Is there breaking changes for older versions? No
    * Does this needs documentation? No
    
    
    Closes #5380 from big-cir/ZEPPELIN-6463.
    
    Signed-off-by: ChanHo Lee <[email protected]>
---
 .../main/java/org/apache/zeppelin/helium/HeliumBundleFactory.java | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git 
a/zeppelin-server/src/main/java/org/apache/zeppelin/helium/HeliumBundleFactory.java
 
b/zeppelin-server/src/main/java/org/apache/zeppelin/helium/HeliumBundleFactory.java
index d17906343b..f6e9389633 100644
--- 
a/zeppelin-server/src/main/java/org/apache/zeppelin/helium/HeliumBundleFactory.java
+++ 
b/zeppelin-server/src/main/java/org/apache/zeppelin/helium/HeliumBundleFactory.java
@@ -305,9 +305,11 @@ public class HeliumBundleFactory {
 
     // 1. setup package.json
     File existingPackageJson = new File(bundleDir, "package.json");
-    JsonReader reader = new JsonReader(new FileReader(existingPackageJson));
-    Map<String, Object> packageJson = gson.fromJson(reader,
-            new TypeToken<Map<String, Object>>(){}.getType());
+    Map<String, Object> packageJson;
+    try (JsonReader reader = new JsonReader(new 
FileReader(existingPackageJson))) {
+      packageJson = gson.fromJson(reader,
+              new TypeToken<Map<String, Object>>(){}.getType());
+    }
     Map<String, String> existingDeps = (Map<String, String>) 
packageJson.get("dependencies");
     String mainFileName = (String) packageJson.get("main");
 

Reply via email to