本文由做者张远道受权网易云社区发布。java
类加载器三杰bootstrap
jvm有三类classloader,分别是bootstrap classloader,extended classloader以及system classloader。windows
bootstrap classloader是系统在启动jvm时默认加载的。当用户在命令行输入java Test时,系统会首先加载jvm。在windows系统下,jvm的路径一般位于%JAVA_HOME%/jdk/jre/client/jvm.dll和%JAVA_HOME%/jdk/jre/server/jvm.dll.安全
bootstrap classloader加载后,会载入extended classloader,并将extended classloader的父类设为bootstrap classloader。而后,bootstrap classloader接着载入system classloader,并将system classloader的父类设为extended classloader。至此,bootstrap--extended--system三级继承结构造成。服务器
bootstrap classloader在jvm启动以后自动加载。bootstrap classloader由c实现,不属于java类。jvm
extended classloader由java实现,一般为sun.misc.Lancher$ExtClassLoader.post
system classloader由java实现,一般为sun.misc.Lancher$AppClassLoader.动画
其中,spa
bootstrap classloader负责加载sun.boot.class.path路径下的.class文件以及jar包。.net
extended classloader负责加载java.ext.dirs路径下的.class文件以及jar包。
system classloader负责加载java.class.path路径下的.class文件以及jar包。
sun.boot.class.path一般对应环境变量CLASSPATH的路径。
java.ext.dirs一般对应JAVA_HOME/jre/lib/ext目录。
java.class.path对应用户自身的类路径。
类加载到何处
据可靠情报,jvm由方法区,堆,栈,pc寄存器和本地方法栈构成。类加载器的任务就是将class二进制文件加载到方法区,供虚拟机模制出在堆中存放的对象。
双亲委托机制
classloader加载类的过程为:
检查被加载类是否被加载。
若是没有被加载则调用父classloader加载该类。
若是一、2不成功,则仍由自身进行类加载。
这种机制又叫双亲委派机制。
双亲委派机制的好处是,避免多个类加载器加载同一个类的不一样拷贝到内存(jvm的方法区)中。由于若是类A由ClassLoaderA加载,同时,又被ClassLoaderB加载,这样,内存中就会存在两份不一样的A的定义,因而造成A既是ClassLoaderA罩的,又是ClassLoaderB罩着,形成灾难性后果。
用户自定义类的加载顺序一般为:
首先调用AppClassLoader加载类,AppClassLoader调用ExtClassLoader,ExtClassLoader调用BootClassLoader,BootClassLoader在sun.boot.class.path寻找改类,没找到,加载失败;ExtClassLoader也未加载类,失败,最后由AppClassLoader加载成功。从这个加载顺序能够看出来,三个类加载器的对类的可见性是不一样的。
java中的类是由java的全名以及类的classloader来限定的。只有当两者彻底同样才会认为是同一个类。不然是不一样的类。所以,能够定义一个同名的类,包名也同样,只要保证该类被不一样的类加载器加载便可。
当前类加载器和线程上下文类加载器
当前类加载器
当前类加载器是指当前方法所在的类使用的类加载器。在程序中使用Class.forName或者Class.getResource抑或Class.class时就是使用的该类加载器。
线程上下文类加载器
线程上下文类加载器能够不遵循双亲委派机制。线程的上下文类加载器有Thread.currentThread().setContextClassLoader()来为当前线程设置线程上下文类加载器。若是没有设置当前线程的上下文类加载器,则继承父类的上下文类加载器。
为何还须要线程上下文类加载器?
考虑一种状况,当咱们的程序必须由jvm的核心代码去加载第三方类的时候。好比jndi,jndi的核心是rt.jar包中实现的,由Bootstrap classloader负责加载,可是jndi必须加载第三方厂商的具体的jndi实现,这个时候调用Bootstrap加载只对其子类加载器可见的类,就会出现失败。这个时候就可使用线程上下文类加载器。
免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐
更多网易技术、产品、运营经验分享请访问网易云社区。
相关文章:
【推荐】 MongoDB的正确使用姿式
【推荐】 扫脸动画
【推荐】 AndroidTV开发(4)