【发布时间】:2013-01-15 17:32:13
【问题描述】:
我在 java 中创建了一个自定义类,用于自定义加载 Groovy 类。
我的 Java 类是这样开始的:
public class ClassLoader {
private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
然后我有一个使用groovyClassLoader 按名称加载类的方法:
Class c = groovyClassLoader.loadClass(className, true, false, true);
一切正常,没有问题。但是,我偶尔想动态地重新加载我的所有 Groovy 类,所以目前我的 java 代码基本上只是重新实例化了我的 ClassLoader 实例。这不会留下对 ClassLoader 实例的剩余引用,这就是您所期望的 GC。
但是,如果我在重新加载几次后检查加载的类(使用 VisualVM 和 MAT),我会看到 Java 类 ClassLoader 只加载了一次,只有一个实例,但有多个 GroovyClassLoader$InnerLoader 实例(在在这种情况下,类加载一次,但有几个实例)和为GroovyClassLoader 加载的几个类(如GroovyClassLoader$1、GroovyClassLoader$2 等)
任何想法为什么尽管 Java ClassLoader 被收集,GroovyClassLoader 及其 InnerLoader 没有被收集?
谢谢!
【问题讨论】:
-
ClassLoader在这里为您的主要 Java 类选择一个相当糟糕的名称,您最好选择一个不与java.lang中的类冲突的名称 -
perm gen 只会在 fullgc 时被清理。使用 VisualVM 触发一些并再次检查。某些 gc,例如 CMS,不会在没有 -XX:+CMSClassUnloadingEnabled 的情况下卸载类
-
@IanRoberts 是的,好点 - 之前已经被这个发现了。会更新
-
@farmer1992 - 是的,谢谢,让 GC 使用这些标志正常工作,确保 perm gen 被扫描(收集其他非 groovy 类)
标签: java memory-leaks groovy classloader