【问题标题】:Why class can not be loaded by URLClassLoader?为什么类不能被 URLClassLoader 加载?
【发布时间】:2016-08-22 14:24:36
【问题描述】:

我想模拟元空间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!");
    }
} 

但是,奇怪的是,加载的类数在达到 jvisualvm 中显示的 1437 时停止增加,并且使用的元空间大小很低,即使 for 循环已经运行了数百万次。似乎每个新的 URLClassLoader 实例都没有加载 ClassA。为什么?

【问题讨论】:

    标签: java classloader urlclassloader metaspace


    【解决方案1】:

    问题是URLClassLoader 是系统类加载器的父级。在加载时,它首先会尝试获取类from parent classloader。所以类只会被加载一次,你不会得到元空间 OOM。

    您需要一个独立的类加载器来完成这项工作。另一种选择是使用cglibasm 库即时生成类。

    同样loadClass 接受的不是规范而是二进制类名。

    【讨论】:

    • 我是ClassLoader的新手,有没有自定义ClassLoader的例子?我的意思是如何创建一个隔离的类加载器?
    • @expoter 有一个关于隔离类加载器的基本操作指南 - blog.markturansky.com/archives/21
    • @expoter 但我想生成类会更容易。看看 cglib 增强器类。
    猜你喜欢
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    • 2019-12-24
    • 2010-10-10
    • 1970-01-01
    • 2012-01-14
    • 1970-01-01
    相关资源
    最近更新 更多