为什么 class 不能被 URLClassLoader 加载?
Why class can not be loaded by URLClassLoader?
我想模拟元空间OOM。我打算通过不同的 URLClassLoader 加载 class 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!");
}
}
但是,奇怪的是加载的 classes 数字在达到 1437 时停止增加,这在 jvisualvm 中显示,并且使用的元空间大小很小,即使 for 循环有 运行 百万次。似乎 ClassA 并没有被每个新的 URLClassLoader 实例加载。为什么?
问题是 URLClassLoader
是系统 classloader 的父级。在加载时,它首先会尝试获取 class from parent classloader。所以 class 只会加载一次,你不会得到元空间 OOM。
您需要一个独立的 classloader 来完成这项工作。另一种选择是使用 cglib or asm 库即时生成 classes。
此外 loadClass
不接受 规范 但 二进制 class 名称。
我想模拟元空间OOM。我打算通过不同的 URLClassLoader 加载 class 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!");
}
}
但是,奇怪的是加载的 classes 数字在达到 1437 时停止增加,这在 jvisualvm 中显示,并且使用的元空间大小很小,即使 for 循环有 运行 百万次。似乎 ClassA 并没有被每个新的 URLClassLoader 实例加载。为什么?
问题是 URLClassLoader
是系统 classloader 的父级。在加载时,它首先会尝试获取 class from parent classloader。所以 class 只会加载一次,你不会得到元空间 OOM。
您需要一个独立的 classloader 来完成这项工作。另一种选择是使用 cglib or asm 库即时生成 classes。
此外 loadClass
不接受 规范 但 二进制 class 名称。