-
Bug
-
Resolution: Unresolved
-
P4
-
11
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
Linux Mint 22
JAVA11
A DESCRIPTION OF THE PROBLEM :
When loading classes through java.net.URLClassLoader#findClass in JDK 11, the internal implementation obtains a Resource instance from URLClassPath.getResource(), but the resource is not explicitly closed after use.
As a result, when the class data is read from a JAR entry or a compressed resource, the associated ZipInflaterInputStream and its native inflater buffers may remain unclosed until GC finalization.
This can cause off-heap (native) memory leaks and delayed resource cleanup, especially in long-running applications that dynamically load and unload classes or modules via multiple URLClassLoader instances.
The relevant code path (from URLClassLoader#findClass) looks like:
result = AccessController.doPrivileged(
new PrivilegedExceptionAction<>() {
public Class<?> run() throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(name, res);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
} catch (ClassFormatError e2) {
if (res.getDataError() != null) {
e2.addSuppressed(res.getDataError());
}
throw e2;
}
} else {
return null;
}
}
}, acc);
Here, res is never closed after defineClass(name, res) returns.
If res internally opens a ZipEntry or InflaterInputStream, the native Inflater may hold memory until it is finalized, leading to continuous native memory growth and potential OutOfMemoryError: Direct buffer memory or OutOfMemoryError: Java heap space depending on allocator pressure.
Expected behavior:
Resource should be closed (or at least its stream released) after successful or failed class definition to ensure deterministic cleanup of underlying native structures.
Environment:
JDK 11 (and possibly later)
Observed on Linux x86_64
Reproducible in long-running class reloading scenarios (e.g., dynamic plugin systems)
Possible fix:
Ensure that Resource (and its underlying stream) is closed in a finally block after defineClass(...) completes, similar to how resource handling is managed elsewhere in the JDK.
REGRESSION : Last worked in version 11
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
just look it
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Need to close the resource immediately
ACTUAL -
Not closed in a timely manner
Linux Mint 22
JAVA11
A DESCRIPTION OF THE PROBLEM :
When loading classes through java.net.URLClassLoader#findClass in JDK 11, the internal implementation obtains a Resource instance from URLClassPath.getResource(), but the resource is not explicitly closed after use.
As a result, when the class data is read from a JAR entry or a compressed resource, the associated ZipInflaterInputStream and its native inflater buffers may remain unclosed until GC finalization.
This can cause off-heap (native) memory leaks and delayed resource cleanup, especially in long-running applications that dynamically load and unload classes or modules via multiple URLClassLoader instances.
The relevant code path (from URLClassLoader#findClass) looks like:
result = AccessController.doPrivileged(
new PrivilegedExceptionAction<>() {
public Class<?> run() throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(name, res);
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
} catch (ClassFormatError e2) {
if (res.getDataError() != null) {
e2.addSuppressed(res.getDataError());
}
throw e2;
}
} else {
return null;
}
}
}, acc);
Here, res is never closed after defineClass(name, res) returns.
If res internally opens a ZipEntry or InflaterInputStream, the native Inflater may hold memory until it is finalized, leading to continuous native memory growth and potential OutOfMemoryError: Direct buffer memory or OutOfMemoryError: Java heap space depending on allocator pressure.
Expected behavior:
Resource should be closed (or at least its stream released) after successful or failed class definition to ensure deterministic cleanup of underlying native structures.
Environment:
JDK 11 (and possibly later)
Observed on Linux x86_64
Reproducible in long-running class reloading scenarios (e.g., dynamic plugin systems)
Possible fix:
Ensure that Resource (and its underlying stream) is closed in a finally block after defineClass(...) completes, similar to how resource handling is managed elsewhere in the JDK.
REGRESSION : Last worked in version 11
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
just look it
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Need to close the resource immediately
ACTUAL -
Not closed in a timely manner