参考文档:java虚拟机(第二版)
了解类加载的过程,首先要了解类的生命周期
image.png
一、加载阶段干了什么?
我们这里说的加载是类的生命过程中加载的这一小部分。那么在这个阶段到底干了什么?
在加载阶段,虚拟机需要完成以下3件事情:
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据
的访问入口。
二、类加载器
从虚拟机的角度,可以分为两类
- 虚拟机内部(C写的虚拟机)的类加载器
- 虚拟机外部的(虚拟机之上的,java写的)类加载器
但从java开发者角度来说,可以分为三类
- 启动类加载器(Bootstrap ClassLoader):这个类将器负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的类库加载到虚拟机内存中。 这块就是C写的,虚拟机内部的类加载器
扩 - 扩展类加载器(Extension ClassLoader):这个加载器由sun.misc.Launcher
$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。 - 应用程序类加载器(Application ClassLoader):这个类加载器由sun.misc.Launcher $AppClassLoader实现。 由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。 它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
tip 这3者是层级上的关系,但并不是继承,实际的实现是通过组合完成的,classloader 里有个属性是 parent classloader
三、parent-delegation model
image.png双亲委派模型是理解类加载器的关键之处,但从理解上来说,或许直接记英文 parent-delegation model更为方便一点,毕竟,双亲是什么,实在是太难理解了
参考资料:https://www.xttblog.com/?p=3051
其实你就记parent-delegation model即可
就是很简单的,先交给parent classloader 去加载,加载不到在用本身的类加载器而已
protected synchronized Class<?>loadClass(String name,boolean resolve)throws ClassNotFoundException
{/
/首先,检查请求的类是否已经被加载过了
Class c=findLoadedClass(name);
if(c==null){
try{
if(parent!=null){
c=parent.loadClass(name,false);
}else{
c=findBootstrapClassOrNull(name);
}}
catch(ClassNotFoundException e){
//如果父类加载器抛出ClassNotFoundException
//说明父类加载器无法完成加载请求
}
if(c==null){
//在父类加载器无法加载的时候
//再调用本身的findClass方法来进行类加载
c=findClass(name);
}}
if(resolve){
resolveClass(c);
}
return c;
}
三、所谓的破坏parent-delegation model
距离JNDI和OSGi
- JNDI---Java Naming and Directory Interface
他的实现是通过启动类加载器去加载第三方的包,但我们知道bootstrap classloader只会去加载java_home/lib下的内容,那么它如何找到第三方的包呢?
为了解决这个问题,Java设计团队只好引入了一个不太优雅的设计:线程上下文类加载器(Thread Context ClassLoader)。 这个类加载器可以通过java.lang.Thread类的setContextClassLoaser()方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那这个类加载器默认就是应用程序类加载
- OSGi
OSGi其实是java模块化的事实标准,OSGi实现模块化热部署的关键则是
它自定义的类加载器机制的实现。 每一个程序模块(OSGi中称为Bundle)都有一个自己的类加载器,当需要更换一个Bundle时,就把Bundle连同类加载器一起换掉以实现代码的热替换。
网友评论