Groovy: re-compile a class from file and memory leaks

369 views Asked by At

As per ref-doc:

A GroovyClassLoader keeps a reference of all the classes it created, so it is easy to create a memory leak. In particular, if you execute the same script twice, if it is a String, then you obtain two distinct classes!

I use a file as a source for parsing but turned caching off:

  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}"

the log output is always

class MyClass <=> class MyClass equal: false

If I comment the line src.cachable = false, then the class instances become equal, but they are NOT re-compiling even though the underlying file has changed.

Hence the question: how can I re-compile classes properly without creating a memory leak?

2

There are 2 answers

0
injecteer On BEST ANSWER

After doing some experiments, I figured out that switching back to using String:

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

the loaded classes do not change in lenght, even if a class has some Closures inside (which appear as classes as well).

0
daggett On

i did the following test and don't see any memory leak.

as for me, the normal GC work.

the link to your class will be alive while any instance of class is alive.

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