我在 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 没有被收集?
谢谢!
最佳答案
也许仍然有一些可访问的对象是您按名称加载的类 c
之一的实例?每个类都保存对其定义类加载器的引用,因此在它加载的所有类的所有实例本身变得无法访问之前,该类加载器无法被 GCd。
如果这还不够,那么问题可能出在 Groovy MetaClass 机制上。当您完成 com.example.ClassLoader
实例后,您可能需要从 MetaClassRegistry
中显式删除您的类:
public void destroy() {
for(Class<?> c : groovyClassLoader.getLoadedClasses()) {
GroovySystem.getMetaClassRegistry().removeMetaClass(c);
}
}
我本希望 Groovy 为您做到这一点,但您可能需要比默认情况下更加主动。
关于java - 使用 Java 中的 GroovyClassLoader - 未 GC 的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14343393/