一、类加载器类型java
当启动一个JVM时,bootstrap 类加载器就会加载java的核心类,例如:rt.jar中的类。bootstrap 类加载器是其余类加载器的parent,它使惟一一个没有parent的类加载器。接下来是extension 类加载器,它以bootstrap 类加载器做为parent,它用来从Java系统变量java.ext.dir中的jar包中加载类的。第三个,也是最重要的一个就是开发者使用的system classpath 类加载器 。它是extension 类加载器 的child,它用来从Java系统变量java.class.path下面加载类,能够经过 -classpath 来指定这个位置。编程
二、delegate委派模型bootstrap
注意类加载器的体系并非“继承”体系,而是一个“委派”体系。大多数类加载器首先会到本身的parent中查找类或者资源,若是找不到,才会在本身的本地进行查找。事实上,类加载器被定义加载哪些在parent中没法加载到的类,这样在较高层级的类加载器上的类型可以被“赋值”为较低类加载器加载的类型。类加载器的委托行为动机是为了不相同的类被加载屡次。tomcat
三、服务端的反委派模型服务器
可是服务器端要求类加载器可以反转委派原则,也就是先加载本地的类,若是加载不到,再到parent中加载。数据结构
JavaEE的 委派模型并发
每一个方块都是一个类加载器,JavaEE规范推荐每一个模块的类加载器先加载本类加载的内容,若是加载不到才回到parent类加载器中尝试加载。反转委派原则的缘由是应用服务器中所携带的类库并非应用所期待的,也许不适合应用开发者,一个常见的例子就是log4j的依赖在容器和不一样的应用中都存在,可是它们的版本大都不一样。app
四、tomcat开启delegate模型spa
Tomcat的 类加载顺序(开启了delegate模式)继承
在Tomcat中,默认的行为是先尝试在Bootstrap和Extension中进行类型加载,若是加载不到则在WebappClassLoader中进行加载,若是仍是找不到则在Common中进行查找。在Alibaba使用的Tomcat开启了delegate模式,所以加载类型时会以parent类加载器优先。
五、类类型定义
在JVM中,如何肯定一个类型实例?答:全类名吗?不是,是类加载器加上全类名。在JVM中,类型被定义在一个叫SystemDictionary 的数据结构中,该数据结构接受类加载器和全类名做为参数,返回类型实例。
六、问题排查
类找不到 | 加载了不正确的类 | 多于一个类被加载 |
ClassNotFoundException NoClassDefFoundError | IncompatibleClassChangeError NoSuchMethodError NoSuchFieldError IllegalAccessError | ClassCastException LinkageError |
IDE class lookup (Ctrl+Shift+T in Eclipse)find . -name “*.jar” -exec jar -tf {} \; | grep DateUtils
使用middleware-detector |
经过在启动参数中加 -verbose:class,观察加载的类来自哪一个jar包 使用middelware-detector |
经过-verbose:class观察 |
转载自并发编程网 – ifeve.com本文连接地址: 深刻浅出ClassLoader