13

我正在做一个小测试来了解元空间内存(Java 8 以上)是如何工作的。当我动态创建 100,000 个类时,元空间内存正在增长(显然),但堆内存也在​​增长。有人可以向我解释为什么会这样吗?

PS:我正在使用 128 MB 的堆和 128 MB 的元空间运行测试。

@Test
public void metaspaceTest() throws CannotCompileException, InterruptedException {

ClassPool cp = ClassPool.getDefault();
System.out.println("started");

for (int i = 0; i <= 100000; i++) {
    Class c = cp.makeClass("br.com.test.GeneratedClass" + i).toClass();
    Thread.sleep(1);
    if (i % 10000 == 0) {
    System.out.println(i);
    }
}

System.out.println("finished");
}

请参阅下面的图片:

在此处输入图像描述

在此处输入图像描述

4

2 回答 2

3

您的类池使用堆内存。它有哈希表、列表和其他东西。它还使用使用堆内存的java反射代码。未经过 gc 处理的堆内存可能是类池中的所有数据结构、一对哈希表、链表、数组列表、池等......例如,您创建的每个类都由该类存储在哈希表中水池。那是一个 100,000 个元素的哈希表。

其次,如果您正在创建的类中有任何静态初始化程序,那将使用堆内存。静态初始化器包括静态字段初始化和静态块代码。

于 2018-05-18T15:14:12.710 回答
1

我特别研究了你的代码ClassPool#makeClass。我注意到有几点导致堆空间随着元空间的增加而增加。

  1. cache是由方法 makeClass 在哈希表中创建的类

受保护的哈希表类;

因此,对于万分之一的课程,它具有每个类别的条目。因此,堆空间也增加了,它不是 GC,因为您的 for 循环仍然使用哈希表引用并不断更新,因此不符合 gc 的条件。

  1. CtNewClass创建类的新实例,它的构造函数定义如下:

      CtNewClass(String name, ClassPool cp, boolean isInterface, CtClass superclass) {
        super(name, cp);
        this.wasChanged = true;
        String superName;
        if (!isInterface && superclass != null) {
            superName = superclass.getName();
        } else {
            superName = null;
        }
    
        this.classfile = new ClassFile(isInterface, name, superName);
        if (isInterface && superclass != null) {
            this.classfile.setInterfaces(new String[]{superclass.getName()});
        }
    
        this.setModifiers(Modifier.setPublic(this.getModifiers()));
        this.hasConstructor = isInterface;
    }
    

在上面的代码中,this.classfile = new ClassFile(isInterface, name, superName);实际上为每个类创建了新的 ConstPool 实例,即为每个实例创建了新的 HashMap 实例,并且这些在堆空间上保留了内存。

HashMap 类;//来自 ConstPool 类

HashMap 字符串;//来自 ConstPool 类

此外,这会创建两个新的 ArrayList。在上面的构造函数中观察this.fields = new ArrayList();this.methods = new ArrayList();声明。另外,一个新的链表this.attributes = new LinkedList();

因此,结论是 ClassPool 有它的缓存管理,它占用了大量的堆空间。然后每个类都有自己的集合来管理属性、常量等。

希望能帮助到你!

于 2018-05-20T07:57:21.853 回答