Groovy中定义了不少ClassLoader,本文将介绍其中绝大多数Groovy脚本都会涉及到的,也是最主要的3个ClassLoader:RootLoader、GroovyClassLoader和GroovyClassLoader.InnerLoader。
注:以下分析的Groovy源代码来自Groovy 2.1.3。
Java的ClassLoader
顾名思义,Java的ClassLoader就是类的装载器,它使JVM可以动态的载入Java类,JVM并不需要知道从什么地方(本地文件、网络等)载入Java类,这些都由ClassLoader完成。
可以说,ClassLoader是Class的命名空间。同一个名字的类可以由多个ClassLoader载入,由不同ClassLoader载入的相同名字的类将被认为是不同的类;而同一个ClassLoader对同一个名字的类只能载入一次。
Java的ClassLoader有一个著名的双亲委派模型(Parent Delegation Model):除了Bootstrap ClassLoader外,每个ClassLoader都有一个parent的ClassLoader,沿着parent最终会追索到Bootstrap ClassLoader;当一个ClassLoader要载入一个类时,会首先委派给parent,如果parent能载入这个类,则返回,否则这个ClassLoader才会尝试去载入这个类。
Java的ClassLoader体系如下,其中箭头指向的是该ClassLoader的parent:
Bootstrap ClassLoader
↑
Extension ClassLoader
↑
System ClassLoader
↑
User Custom ClassLoader // 不一定有
更多关于Java的ClassLoader的信息请参考以下资料:
Groovy的ClassLoader
我们首先通过一个脚本来看一下,一个Groovy脚本的ClassLoader以及它的祖先们分别是什么:
def cl = this.class.classLoader
while (cl) {
println cl
cl = cl.parent
}
输出如下:
groovy.lang.GroovyClassLoader$InnerLoader@18622f3
groovy.lang.GroovyClassLoader@147c1db
org.codehaus.groovy.tools.RootLoader@186db54
sun.misc.Launcher$AppClassLoader@192d342
sun.misc.Launcher$ExtClassLoader@6b97fd
我们从而得出Groovy的ClassLoader体系:
null // 即Bootstrap ClassLoader
↑
sun.misc.Launcher.ExtClassLoader // 即Extension ClassLoader
↑
sun.misc.Launcher.AppClassLoader // 即System ClassLoader
↑
org.codehaus.groovy.tools.RootLoader // 以下为User Custom ClassLoader
↑
groovy.lang.GroovyClassLoader
↑
groovy.lang.GroovyClassLoader.InnerLoader
下面我们分别介绍一下RootLoader、GroovyClassLoader和GroovyClassLoader.InnerLoader。
Groovy脚本启动过程
要介绍RootLoader前,我们需要介绍一下Groovy脚本的启动过程。
当我们在命令行输入“groovy SomeScript”来运行脚本时,调用的是shell脚本$GROOVY_HOME/bin/groovy:
#…
startGroovy groovy.ui.GroovyMain "$@"
其中startGroovy定义在$GROOVY_HOME/bin/startGroovy中:
#…
STARTER_CLASSPATH="$GROOVY_HOME/lib/groovy-2.1.3.jar"
#…
startGroovy ( ) {
CLASS=$1
shift
# Start the Profiler or the JVM
if $useprofiler ; then
runProfiler
else
exec "$JAVACMD" $JAVA_OPTS \
-classpath "$STARTER_CLASSPATH" \
-Dscript.name="$SCRIPT_PATH" \
-Dprogram.name="$PROGNAME" \
-Dgroovy.starter.conf="$GROOVY_CONF" \
-Dgroovy.home="$GROOVY_HOME" \
-Dtools.jar="$TOOLS_JAR" \
$STARTER_MAIN_CLASS \
--main $CLASS \
--conf "$GROOVY_CONF" \
--classpath "$CP" \
"$@"
fi
}
STARTER_MAIN_CLASS=org.codehaus.groovy.tools.GroovyStarter