-
Bug
-
Resolution: Fixed
-
P2
-
8u25, 9
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8227315 | openjdk8u232 | Brent Christian | P2 | Resolved | Fixed | b01 |
JDK-8224593 | 8u231 | Ivan Gerasimov | P2 | Closed | Fixed | b01 |
JDK-8229633 | emb-8u231 | Ivan Gerasimov | P2 | Resolved | Fixed | b01 |
FULL PRODUCT VERSION :
java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
Class.forName use with Classloader.getSystemClassLoader and policy and security manager activated provoke a memory leak.
REGRESSION. Last worked in version 8u66
ADDITIONAL REGRESSION INFORMATION:
Don't know exactly the version.
On Mac OS X it works with 1.6.0_65 and 1.8.0_05.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the 2 classes with a maven project
java -jar target/classfornameleak-0.0.1-SNAPSHOT.jar
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
classloader name: leaked classloader
OK no bug
ACTUAL -
classloader name: leaked classloader
Not yet GC
Not yet GC
Not yet GC
Not yet GC
Not yet GC
...
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package classfornameleak;
import java.util.List;
public class ClassForName implements Runnable {
public void run() {
System.out.println("classloader name: " + ClassForName.class.getClassLoader());
try {
Class.forName(List.class.getName(), false, ClassLoader.getSystemClassLoader());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
-----------
package classfornameleak;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.Permission;
import java.security.Policy;
import java.security.ProtectionDomain;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
public class ClassForNameLeak {
public static WeakReference<ClassLoader> init() throws Exception {
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(final Permission perm) {
return;
}
});
Policy.setPolicy(new Policy() {
@Override
public boolean implies(final ProtectionDomain domain, final Permission permission) {
return true;
}
});
URL resource = ClassForNameLeak.class.getResource("ClassForName.class");
File jarFile = File.createTempFile("cfn", ".jar");
JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarFile));
jarFile.deleteOnExit();
ZipEntry zipEntry = new ZipEntry("classfornameleak/");
jarOutputStream.putNextEntry(zipEntry);
zipEntry = new ZipEntry("classfornameleak/ClassForName.class");
byte[] buffer = new byte[1024];
InputStream openStream = resource.openStream();
jarOutputStream.putNextEntry(zipEntry);
while (true) {
int count = openStream.read(buffer);
if (count == -1) {
break;
}
jarOutputStream.write(buffer, 0, count);
}
jarOutputStream.closeEntry();
jarOutputStream.close();
ClassLoader classLoader = new URLClassLoader(new URL[] {jarFile.toURI().toURL()}) {
@Override
public Class<?> loadClass(final String name) throws ClassNotFoundException {
if (ClassForName.class.getName().equals(name)) {
return findClass(name);
}
return super.loadClass(name);
}
@Override
public String toString() {
return "leaked classloader";
}
};
Class<?> loadClass = classLoader.loadClass(ClassForName.class.getName());
((Runnable) loadClass.newInstance()).run();
return new WeakReference<ClassLoader>(classLoader);
}
public static void main(final String[] args) throws Exception {
WeakReference<ClassLoader> weakReference = init();
for (int i = 0; i < 10; i++) {
System.gc();
}
while (weakReference.get() != null) {
System.out.println("Not yet GC");
System.gc();
Thread.sleep(100);
}
System.out.println("OK no bug");
}
}
------------------
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>classfornameleak</groupId>
<artifactId>classfornameleak</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>classfornameleak.ClassForNameLeak</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Not found
java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
Class.forName use with Classloader.getSystemClassLoader and policy and security manager activated provoke a memory leak.
REGRESSION. Last worked in version 8u66
ADDITIONAL REGRESSION INFORMATION:
Don't know exactly the version.
On Mac OS X it works with 1.6.0_65 and 1.8.0_05.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the 2 classes with a maven project
java -jar target/classfornameleak-0.0.1-SNAPSHOT.jar
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
classloader name: leaked classloader
OK no bug
ACTUAL -
classloader name: leaked classloader
Not yet GC
Not yet GC
Not yet GC
Not yet GC
Not yet GC
...
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package classfornameleak;
import java.util.List;
public class ClassForName implements Runnable {
public void run() {
System.out.println("classloader name: " + ClassForName.class.getClassLoader());
try {
Class.forName(List.class.getName(), false, ClassLoader.getSystemClassLoader());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
-----------
package classfornameleak;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.Permission;
import java.security.Policy;
import java.security.ProtectionDomain;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
public class ClassForNameLeak {
public static WeakReference<ClassLoader> init() throws Exception {
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(final Permission perm) {
return;
}
});
Policy.setPolicy(new Policy() {
@Override
public boolean implies(final ProtectionDomain domain, final Permission permission) {
return true;
}
});
URL resource = ClassForNameLeak.class.getResource("ClassForName.class");
File jarFile = File.createTempFile("cfn", ".jar");
JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarFile));
jarFile.deleteOnExit();
ZipEntry zipEntry = new ZipEntry("classfornameleak/");
jarOutputStream.putNextEntry(zipEntry);
zipEntry = new ZipEntry("classfornameleak/ClassForName.class");
byte[] buffer = new byte[1024];
InputStream openStream = resource.openStream();
jarOutputStream.putNextEntry(zipEntry);
while (true) {
int count = openStream.read(buffer);
if (count == -1) {
break;
}
jarOutputStream.write(buffer, 0, count);
}
jarOutputStream.closeEntry();
jarOutputStream.close();
ClassLoader classLoader = new URLClassLoader(new URL[] {jarFile.toURI().toURL()}) {
@Override
public Class<?> loadClass(final String name) throws ClassNotFoundException {
if (ClassForName.class.getName().equals(name)) {
return findClass(name);
}
return super.loadClass(name);
}
@Override
public String toString() {
return "leaked classloader";
}
};
Class<?> loadClass = classLoader.loadClass(ClassForName.class.getName());
((Runnable) loadClass.newInstance()).run();
return new WeakReference<ClassLoader>(classLoader);
}
public static void main(final String[] args) throws Exception {
WeakReference<ClassLoader> weakReference = init();
for (int i = 0; i < 10; i++) {
System.gc();
}
while (weakReference.get() != null) {
System.out.println("Not yet GC");
System.gc();
Thread.sleep(100);
}
System.out.println("OK no bug");
}
}
------------------
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>classfornameleak</groupId>
<artifactId>classfornameleak</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>classfornameleak.ClassForNameLeak</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Not found
- backported by
-
JDK-8227315 Class.forName causes memory leak
- Resolved
-
JDK-8229633 Class.forName causes memory leak
- Resolved
-
JDK-8224593 Class.forName causes memory leak
- Closed
- relates to
-
JDK-8168682 jdk/test/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java fails with -Xcomp: ClassLoader was never enqueued!
- Resolved