Groovy: 从文件和内存泄漏中重新编译 class
Groovy: re-compile a class from file and memory leaks
根据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!
我使用一个文件作为解析源,但关闭了缓存:
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 equal: false
如果我注释行 src.cachable = false
,则 class 个实例变得相等,但即使基础文件已更改,它们也不会重新编译。
因此问题来了:如何正确地重新编译 classes 而不会造成内存泄漏?
我做了以下测试,没有发现任何内存泄漏。
对于我来说,正常的 GC 工作。
您的 class 的 link 将在 class 的任何实例处于活动状态时处于活动状态。
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)}"
}
经过一些实验后,我发现切换回使用 String:
String src = 'class A {}'
Class clazz = groovyClassLoader.parseClass src
log.info groovyClassLoader.loadedClasses.join( ', ' )
加载的 classes 的长度不会改变,即使 class 内部有一些闭包(也显示为 classes)。
根据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!
我使用一个文件作为解析源,但关闭了缓存:
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 equal: false
如果我注释行 src.cachable = false
,则 class 个实例变得相等,但即使基础文件已更改,它们也不会重新编译。
因此问题来了:如何正确地重新编译 classes 而不会造成内存泄漏?
我做了以下测试,没有发现任何内存泄漏。
对于我来说,正常的 GC 工作。
您的 class 的 link 将在 class 的任何实例处于活动状态时处于活动状态。
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)}"
}
经过一些实验后,我发现切换回使用 String:
String src = 'class A {}'
Class clazz = groovyClassLoader.parseClass src
log.info groovyClassLoader.loadedClasses.join( ', ' )
加载的 classes 的长度不会改变,即使 class 内部有一些闭包(也显示为 classes)。