Ответ 1
Я изучил ваш код, особенно ClassPool#makeClass
. Есть несколько моментов, которые я заметил, которые заставляют пространство кучи увеличиваться по мере увеличения metaspace.
- Это
cache
классов, созданных методом makeClass в хэш - таблице
защищенные классы Hashtable;
Итак, для 10-го миллиона классов, у него есть запись для каждого из них. Следовательно, Heap Space тоже увеличивается, и это не GC, поскольку ссылка hashtable по-прежнему используется вашим циклом for и постоянно обновляется, следовательно, не подходит для gc.
-
CtNewClass
создает новый экземпляр класса и имеет определение конструктора, как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
Кроме того, это создает два новых ArrayLists. Наблюдайте this.fields = new ArrayList();
и this.methods = new ArrayList();
в конструкторе. Кроме того, новый связанный список this.attributes = new LinkedList();
,
Следовательно, вывод заключается в том, что ClassPool имеет управление кешем, которое занимает большое количество кучи. Тогда каждый класс имеет свой собственный набор коллекций для управления свойствами, константами и т.д.
Надеюсь, поможет!