Groovy内存机制详解

groovy每执行一次脚本,都会生成一个脚本的class对象,并new一个InnerLoader去加载这个对象。

所有的脚本都是由GroovyClassLoader加载的,每次加载脚本都会生成一个新的InnerLoader去加载脚本。

Groovy会把脚本编译为一个名为Scriptxx的类,这个脚本类运行时用反射生成一个实例并调用它的MAIN函数执行。

每次groovy编译脚本后,都会缓存该脚本的Class对象,下次编译该脚本时,会优先从缓存中读取。

缓存的Map由GroovyClassLoader持有,key是脚本的类名,而脚本的类名在不同的编译场景下(从文件读取脚本/从流读取脚本/从字符串读取脚本)其命名规则不同。比如:

"script" + System.currentTimeMillis() + Math.abs(text.hashCode()) + ".groovy"。

ClassLoader对于同一个名字的类只能加载一次,如果都由GroovyClassLoader加载,那么当一个脚本里定义了C这个类之后,另外一个脚本再定义一个C类的话,GroovyClassLoader就无法加载了。

Java的classpath中只包含了Groovy的jar包,而不包含Groovy依赖的第三方jar包,而Groovy的classpath则包含了Groovy以及其依赖的所有第三方jar包。

RootLoader:管理了Groovy的classpath,负责加载Groovy及其依赖的第三方库中的类,它不是使用双亲委派模型。

GroovyClassLoader主要负责在运行时编译groovy源代码为Class的工作,从而使Groovy实现了将groovy源代码动态加载为Class的功能。 

GroovyClassLoader.InnerLoader:Groovy脚本类的直接ClassLoader,它将加载工作委派给GroovyClassLoader,它的存在是为了支持不同源码里使用相同的类名,以及加载的类能顺利被GC。

GroovyShell.parse()内部其实也就是调用GroovyClassLoader.parseClass()去解析Groovy脚本并生成Class实例(会是groovy.lang.Script的子类),然后调用Class.newInstance()构造出一个新的实例以Script类型的引用返回出来。

 

自己的学习总结,谢谢观看!

posted @ 2019-01-30 14:13  JXY_Super  阅读(1468)  评论(0编辑  收藏  举报