【问题标题】:Using GroovyClassLoader from Java - Classes not GC'd使用 Java 中的 GroovyClassLoader - 没有 GC 的类
【发布时间】: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$1GroovyClassLoader$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


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-15
      • 2020-07-22
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多