ClassLoader心得
Posted sten
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ClassLoader心得相关的知识,希望对你有一定的参考价值。
我们都知道,jvm执行的代码,都是通过jvm加载系统加入的。加载系统的第一步是通过ClassLoader加载class二进制信息,jvm规范中并没有规定class的来源类型,这就给jvm的实现这块很大的灵活。可以放在数据库里,可以放在网络的其他地方(以前的applet),zip文件等。现在大多数都是放在zip包里,我们引入其他class都是通过引入zip包的形式。
ClassLoader关系结构如下
BootStrap ClassLoader
|
Extension ClassLoader
|
System ClassLoader
|
Custom ClassLoader
BootStrap ClassLoader 是由C++编写,虚拟机的一部分,只用来加载核心类。负责加载目录[JAVA_HOME]/bin下的jar,或者被参数 -DXbootclasspath说指定目录的jar,并且是jvm识别的。
Extension ClassLoader是java编写的,对应java系统中的ExtClassLoader类,负责加载java里的ext包里的类。
System ClassLoader 也是由java编写,对应系统中的AppClassLoader类,负责加载应用中的代码。
Custom ClassLoader是自己定义的ClassLoader,同AppClassLoader类,不同的事,他限定了只加载一部分应用中的代码。
ClassLoader的双亲委派模型
双亲委派模型,主要是整理java加载的秩序性,限定核心,扩展类的重复加载。
BootStrap ClassLoader —> Extension ClassLoader —> System ClassLoader —> Custom ClassLoader 的父子关系,是由组合关系组成的。加载类时,先请求parent加载器,如果加载成功就返回;否则自己再作加载。这样有个好处是核心jar类或者扩展jar类可以做到唯一性,不会每个ClassLoader都加载他。
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 查找class是否被加载
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// 先让父加载ClassLoader加载类
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// 启动类ClassLoader加载
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
// 仍然没加载到,自己去加载
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
从方法中,我们看到,ClassLoader先判断类有没有被加载,如果有直接返回;如果没有在请求父ClassLoader,父ClassLoader在递归相同的操作;如果父ClassLoader为null,表面为启动类加载器,换成启动类加载器加载;如果还没加载,在伦到自己加载。
从方法的修饰词 protected 可以看出,ClassLoader的双亲模式是不牢靠的,只要自定义的ClassLoader重载这个方法,就可能破坏双亲委派模型。
以上是关于ClassLoader心得的主要内容,如果未能解决你的问题,请参考以下文章
FLinkaccess closed classloader classloader.check-leaked-classloader
FlinkFlink classloader.check-leaked-classloader