2

我在 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$1GroovyClassLoader$2等)加载的几个类

任何想法为什么尽管ClassLoader收集了 Java,但GroovyClassLoader它的 InnerLoader 没有被收集?

谢谢!

4

2 回答 2

2

也许仍然有一些可访问的对象是c您按名称加载的类之一的实例?每个类都持有对其定义类加载器的引用,因此类加载器不能被 GCd,直到它加载的所有类的所有实例本身都变得不可访问。

如果这还不够,那么问题可能出在 Groovy MetaClass 机制上。MetaClassRegistry您可能需要在完成com.example.ClassLoader实例后明确删除您的类:

public void destroy() {
  for(Class<?> c : groovyClassLoader.getLoadedClasses()) {
    GroovySystem.getMetaClassRegistry().removeMetaClass(c);
  }
}

我原以为 Groovy 会为您执行此操作,但您可能需要比默认情况下更主动。

于 2013-01-15T18:06:20.210 回答
1

根据我最近在 Play 框架中使用 Groovy 模板引擎的经验,当应用程序代码无法访问其编译的类时,Groovy 不会清理元类注册表。

https://hoangx281283.wordpress.com/2014/07/24/unload-groovy-classes/

于 2014-07-25T01:56:31.743 回答