赞
踩
(1)什么是类加载子系统
(2)类加载器的三大特点
(3)类加载子系统由三个模块组成
加载器(ClassLoader)
加载器负责将类的字节码加载到JVM中
三种类型的加载器
启动类加载器(Bootstrap ClassLoader)
平台类加载器(Platform ClassLoader)
应用程序类加载器(Application ClassLoader)
类加载器用父类加载器、子类加载器这样的名字,虽然看似是继承关系,实际上是组合(Composition)关系
链接器(Linker)
初始化器(Initializer)
(1)为啥需要这个双亲委派模型
(2)什么是双亲委派模型
(3)什么是JDK9模块化系统
(4)新版本的JDK9后的类加载器
模块化系统中的类加载器可以分为两种类型
应用程序类加载器,加载器用于加载应用程序中的模块; 平台类加载器,加载器用于加载 JDK 中的模块
当平台及应用程序类加载器收到类加载请求,在委派给父加载器加载前,要先判断该类是否能够归属到某一个系统模块中
如果findLoadedModule
可以找到这样的归属关系,就要优先委派给负责那个模块的加载器完成加载
在模块化系统中,每个模块都有一个类加载器,它根据模块的依赖关系来加载模块中的类和依赖的模块中的类
在模块化系统中,类加载器的原理与传统的类加载器相似,都是采用双亲委派模型
当一个类被加载时,类加载器首先会检查自己是否已经加载过该类,如果没有,则会将该类的加载请求委托给其父加载器
直到达到顶层的 Bootstrap ClassLoader 为止,如果所有的父加载器都无法加载该类,则由当前加载器自己来加载该类
(5)新版本的JDK9后的类加载器
模块化系统中的类加载器可以分为两种类型
应用程序类加载器,加载器用于加载应用程序中的模块; 平台类加载器,加载器用于加载 JDK 中的模块
当平台及应用程序类加载器收到类加载请求,在委派给父加载器加载前,要先判断该类是否能够归属到某一个系统模块中
如果findLoadedModule
可以找到这样的归属关系,就要优先委派给负责那个模块的加载器完成加载
在模块化系统中,每个模块都有一个类加载器,它根据模块的依赖关系来加载模块中的类和依赖的模块中的类
在模块化系统中,类加载器的原理与传统的类加载器相似,都是采用双亲委派模型
当一个类被加载时,类加载器首先会检查自己是否已经加载过该类,如果没有,则会将该类的加载请求委托给其父加载器
直到达到顶层的 Bootstrap ClassLoader 为止,如果所有的父加载器都无法加载该类,则由当前加载器自己来加载该类
BuiltinClassLoader
(1)为什么需要用到自定义类加载器
(2)ClassLoader核心源码解读
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
//首先检查这个class是否已经加载过了
Class<?> c = findLoadedClass(name);
//c==null表示没有加载
if (c == null) {
long t0 = System.nanoTime();
try {
// 如果有父类的加载器则让父类加载器加载
if (parent != null) {
c = parent.loadClass(name, false);
} else {
//如果父类的加载器为空 则递归到bootStrapClassloader,这里就是双亲委派模型的实现
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
/如果bootstrapClassLoader 仍然没有加载过,则自己去加载class
long t1 = System.nanoTime();
//是一个空方法,返回内容为class,方法其中没有任何内容,只抛出了个异常,说明这个方法需要开发者自己去实现
c = findClass(name);
// this is the defining class loader; record the stats
PerfCounter.getParentDelegationTime().addTime(t1 - t0);
PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
注意两个方法区别
findClass( ) 用于写类加载逻辑
loadClass( )方法的逻辑里,如果父类加载器加载失败则会调用自己的findClass( )方法完成加载,保证了双亲委派规则
@Data
public class User {
private String name;
private int age;
}
javac User.java
public class MyClassLoader extends ClassLoader{
private String codePath;
public MyClassLoader(String codePath){
this.codePath = codePath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String fileName = codePath + name + ".class";
System.out.println(fileName);
//获取输入流
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName));
ByteArrayOutputStream bos = new ByteArrayOutputStream();) {
int len;
byte[] data = new byte[1024];
while ((len = bis.read(data)) != -1) {
bos.write(data, 0, len);
}
//获取内存中字节数组
byte[] byteCode = bos.toByteArray();
//执行 defineClass 将字节数组转成Class对象
Class<?> defineClass = defineClass(null, byteCode, 0, byteCode.length);
return defineClass;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public class Main {
public static void main(String[] args) throws Exception {
//测试自定义类加载器
MyClassLoader myClassLoader = new MyClassLoader("/Users/mac/IdeaProjects/jvm-test/src/main/java/com/lixiang/");
//加载指定类
Class<?> clazz = myClassLoader.loadClass("User");
//创建对像
Object obj = clazz.getDeclaredConstructor().newInstance();
System.out.println( "当前类:"+obj.getClass().getName());
System.out.println( "当前类加载器:"+obj.getClass().getClassLoader().getClass().getName());
}
}
使用自定义的类加载器进行加载 。
问题:两个不同的类加载器加载同一个class类,JVM是否认为它们相同
编码验证
public static void main(String[] args) throws Exception {
//测试不同classloader加载同个class
MyClassLoader myClassLoader = new MyClassLoader("/Users/mac/IdeaProjects/jvm-test/src/main/java/com/lixiang/");
//用自定义的类加载器加载User.class
Class<?> clazz = myClassLoader.loadClass("User");
//创建对象
Object obj = clazz.getDeclaredConstructor().newInstance();
//判断创建的对象是否是User对象
System.out.println("判断创建的对象是否是User对象:"+(obj instanceof User));
}
//打印相应的类加载器
System.out.println("obj 的 类加载器:"+obj.getClass().getClassLoader().getClass().getName());
System.out.println("User 的 类加载器:"+User.class.getClassLoader().getClass().getName());
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。