【问题标题】:Groovy: re-compile a class from file and memory leaksGroovy:从文件和内存泄漏中重新编译一个类
【发布时间】:2018-03-16 22:29:10
【问题描述】:

根据ref-doc

GroovyClassLoader 保留了它创建的所有类的引用,因此很容易造成内存泄漏。特别是,如果您执行两次相同的脚本,如果它是一个字符串,那么您将获得两个不同的类!

我使用文件作为解析源,但关闭了缓存:

  GroovyCodeSource src = new GroovyCodeSource( file )
  src.cachable = false
  Class clazz = groovyClassLoader.parseClass src
  Class clazz1 = groovyClassLoader.parseClass src
  log.info "$clazz <=> $clazz1 equal: ${clazz == clazz1}"

日志输出总是

class MyClass class MyClass 等于:false

如果我注释src.cachable = false 行,则类实例变得相等,但即使基础文件已更改,它们也不会重新编译。

因此问题是:如何正确地重新编译类而不造成内存泄漏?

【问题讨论】:

    标签: groovy memory-leaks groovyclassloader


    【解决方案1】:

    我做了以下测试,没有发现任何内存泄漏。

    至于我,正常的 GC 工作。

    当任何类的实例处于活动状态时,指向你的类的链接将处于活动状态。

    GroovyCodeSource src = new GroovyCodeSource( 'println "hello world"', 'Test', '/' )
    src.cachable = false
    
    def cl=this.getClass().getClassLoader()
    
    for(int i=0;i<1000000;i++){
        Class clazz = cl.parseClass src
        if(i%10000==0)println "$i :: $clazz :: ${System.identityHashCode(clazz)}"
    }
    

    【讨论】:

      【解决方案2】:

      做了一些实验后,我发现切换回使用字符串:

      String src = 'class A {}'
      Class clazz = groovyClassLoader.parseClass src
      log.info groovyClassLoader.loadedClasses.join( ', ' )
      

      加载的类的长度不会改变,即使一个类内部有一些闭包(也显示为类)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-15
        • 2012-06-22
        • 2010-10-17
        • 1970-01-01
        • 2012-11-19
        • 1970-01-01
        • 2021-09-21
        相关资源
        最近更新 更多