Groovy:从文件和内存泄漏中重新编译一个类

时间:2017-10-05 10:23:24

标签: groovy memory-leaks groovyclassloader

根据ref-doc

  

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

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

  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&lt; =&gt; class MyClass equal:false

如果我对行src.cachable = false发表评论,那么类实例会变得相等,但即使基础文件发生了变化,它们也不会重新编译。

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

2 个答案:

答案 0 :(得分: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)}"
}

enter image description here

答案 1 :(得分:0)

在做了一些实验后,我发现切换回使用String:

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

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