我想模拟元空间OOM。我打算用不同的URLClassLoader加载类ClassA
,这里是代码:
package classloader;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
class ClassA {
public void method(String input){}
}
public class ClassMetadataLeakSimulator {
private final static int NB_ITERATIONS_DEFAULT = 50000;
public static void main(String[] args) {
System.out.println("Class metadata leak simulator");
int nbIterations = (args != null && args.length == 1) ? Integer.parseInt(args[0]) : NB_ITERATIONS_DEFAULT;
try {
List<ClassLoader> list = new ArrayList<>();
URL url = new File(".").toURI().toURL();
URL[] urls = new URL[]{url};
System.out.println(url);
for (int i = 0; i < nbIterations; i++) {
URLClassLoader newClassLoader = new URLClassLoader(urls);
list.add(newClassLoader);
newClassLoader.loadClass("classloader.ClassA");
}
}
catch (Throwable any) {
System.out.println("ERROR: " + any);
}
System.out.println("Done!");
}
}
但是,奇怪的是当加载的类数量达到1437(jvisualvm中显示)时停止增加,并且使用的元空间大小很低,即使for循环已经运行了数百万次。似乎每个新的URLClassLoader实例都没有加载ClassA。为什么呢?
答案 0 :(得分:1)
问题是URLClassLoader
是系统类加载器的父级。在加载时,它会首先尝试获取类from parent classloader。所以类只会被加载一次,你不会得到元空间OOM。
您需要一个独立的类加载器来完成这项工作。另一个选项是使用cglib或asm库生成类。
同样loadClass
不接受规范但二进制类名。