深入理解java虚拟机(8):类加载器

1、虚拟机将类加载阶段通过一个类的限定名来获取描述该类的二进制文件流的动作放到java虚拟机以外,以便让应用程序决定去如何获取所需的类,实现这个动作的类被称为类加载器。对于任意一个类需要有它的类加载器和这个类本身一同确立其在java虚拟机中的唯一性,每一个类加载器都有一个独立的类名称空间,两个类相等的前提就是它们由同一个类加载器加载。

package org.xiaofeiyang.classloader;

import java.io.IOException;
import java.io.InputStream;

/**
* @author: yangchun
* @description:
* @date: Created in 2019-11-23 22:39
*/
public class ClassLoaderTest {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader myLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
try {
String fileName = name.substring(name.lastIndexOf(".")+1)+".class";
InputStream is = getClass().getResourceAsStream(fileName);
if(is==null){
return super.loadClass(name);
}
byte[] res = new byte[is.available()];
is.read(res);
return defineClass(name,res,0,res.length);
}catch (IOException e){
throw new ClassNotFoundException(name);
}
}
};
Object obj = myLoader.loadClass("org.xiaofeiyang.classloader.ClassLoaderTest");
System.out.println(obj.getClass());
System.out.println(obj instanceof org.xiaofeiyang.classloader.ClassLoaderTest);
}
}
输出如下

class java.lang.Class
false

2、双亲委派模型

两种类加载器,启动类加载器,一种是启动类加载器,这个类加载器是虚拟机的一部分,由c++实现,另一种是其他所有类加载器,由java语言自身实现,独立于java虚拟机之外,全部继承与抽象类java.lang.classLoader。

1)启动类加载器,负责将java_home下lib文件夹中java虚拟机可以识别的文件入rt.jar类库加载到虚拟机中内存中。

2)扩展类加载器,这个类加载器由sun.misc.Launcher$ExtClassLoader实现,这个类加载器是一般负责加载java_home\lib\ext下的类库,开发人员可以直接使用这个类加载器。

3)应用程序类加载器,这个类加载器由sun.misc.Launcher$App-ClassLoader实现,这个类加载器是ClassLoader中getSystemClassLoader()方法的返回值,所以称为系统类加载器,一般负责加载classpath下的类库,应用程序一般默认使用这个类加载器。

 类层次之间的这种关系被称为双亲委派模型,双亲委派模型要求除了顶层类加载器其余的必须有父类加载器,采用组合的办法来复用父类加载器的代码。子类收到加载请求会让父类去加载,如果加载不到才会自己去主动加载。好处是有优先级,rt中的类不会被替换,保证了java虚拟机的稳定运行。双亲委派模型的代码都在java.lang.ClassLoader中代码如下

 双亲委派模型很好的解决了各个类加载器的基础类统一问题。

双亲委派模型被破坏有以下三种情况

1)继承java.lang.ClassLoader重写loadClass方法,避免问题需要重写findClass方法

2)jndi代码由启动类加载器加载,需要调用在classpath下的jndi接口提供者的代码,就通过设置线程上下文类加载器,Thread Context ClassLoader如果没有设置就是默认继承父线程,就是应用程序类加载器

,也就是父类加载器请求子类加载器去完成类加载动作。

3)OSGI实现模块化热部署,自定义类加载器每一个程序模块Bundle都有一个类加载器,如果需要替换就将Bundle连同类加载器一起替换掉。

osgi按如下顺序进行类搜索

猜你喜欢

转载自www.cnblogs.com/xiaofeiyang/p/11920846.html