Description
ManifestVersionReader.readManifestFiles() enumerates every META-INF/MANIFEST.MF on the classpath and passes URL.openStream() into new Manifest(InputStream) without closing the stream.
java.util.jar.Manifest(InputStream) reads the stream and does not close it. For jar: URLs that stream is a ZipFileInflaterInputStream. Closing it is what calls ZipFile$CleanableResource.releaseInflater(). If it is never closed, each JAR leaves a live java.util.zip.Inflater (~64 KiB zlib window).
This still matches main and 8.41.0 / 8.52.0.
Call site
final Enumeration<URL> resources =
ClassLoader.getSystemClassLoader().getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
try {
final Manifest manifest = new Manifest(resources.nextElement().openStream());
// ...
} catch (Exception e) {
// ignore
}
}
Triggered from ManifestVersionDetector.checkForMixedVersions() → InitUtil.shouldInit() → Sentry.init().
Observed
Compose Desktop / packaged JVM app with ~80 JARs on the classpath (sentry-java 8.41.0):
GC.class_histogram: 168 live java.util.zip.Inflater
- async-profiler
event=java.util.zip.Inflater.<init> from process start: 79 / 174 constructors (45%) are
java.util.zip.Inflater.<init>
java.util.zip.ZipFile$CleanableResource.getInflater
java.util.zip.ZipFile$ZipFileInflaterInputStream.<init>
java.util.zip.ZipFile.getInputStream
java.util.jar.JarFile.getBytes
java.util.jar.JarFile.checkForSpecialAttributes
java.util.jar.JarFile.isMultiRelease
java.util.jar.JarFile.getEntry
sun.net.www.protocol.jar.URLJarFile.getEntry
sun.net.www.protocol.jar.JarURLConnection.connect
sun.net.www.protocol.jar.JarURLConnection.getInputStream
java.net.URL.openStream
io.sentry.internal.ManifestVersionReader.readManifestFiles
io.sentry.ManifestVersionDetector.checkForMixedVersions
io.sentry.util.InitUtil.shouldInit
io.sentry.Sentry.init
Suggested fix
try (InputStream is = resources.nextElement().openStream()) {
final Manifest manifest = new Manifest(is);
// existing attribute handling
} catch (Exception e) {
// ignore
}
Manifest does not take ownership of the stream, so try-with-resources is required even on the success path.
Description
ManifestVersionReader.readManifestFiles()enumerates everyMETA-INF/MANIFEST.MFon the classpath and passesURL.openStream()intonew Manifest(InputStream)without closing the stream.java.util.jar.Manifest(InputStream)reads the stream and does not close it. Forjar:URLs that stream is aZipFileInflaterInputStream. Closing it is what callsZipFile$CleanableResource.releaseInflater(). If it is never closed, each JAR leaves a livejava.util.zip.Inflater(~64 KiB zlib window).This still matches main and 8.41.0 / 8.52.0.
Call site
Triggered from
ManifestVersionDetector.checkForMixedVersions()→InitUtil.shouldInit()→Sentry.init().Observed
Compose Desktop / packaged JVM app with ~80 JARs on the classpath (
sentry-java8.41.0):GC.class_histogram: 168 livejava.util.zip.Inflaterevent=java.util.zip.Inflater.<init>from process start: 79 / 174 constructors (45%) areSuggested fix
Manifestdoes not take ownership of the stream, so try-with-resources is required even on the success path.