标签:使用 ash 运行时 lan pat time 一个 就是 存在
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类型的引用返回出来。
自己的学习总结,谢谢观看!
标签:使用 ash 运行时 lan pat time 一个 就是 存在
原文地址:https://www.cnblogs.com/jsersudo/p/10337888.html