You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by ch...@apache.org on 2026/08/06 02:10:29 UTC
(zeppelin) branch master updated: [ZEPPELIN-6463] Close the package.json reader in HeliumBundleFactory with try-with-resources
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 <99...@users.noreply.github.com>
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 <ch...@apache.org>
---
.../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");