类加载流程
类加载流程,先加载 Bootstrap ClassLoader 启动类加载即最顶层的加载类。这部分由 C ++ 编写。继续再次加载 Extention ClassLoader 扩展类加载器由 Bootstrap ClassLoader 加载,加载进入内存。继续再次加载 Application ClassLoader 应用类加载器,即系统即在此,加载当前应用下的类最后再次加载 ClassLoader 类
双亲委派模型
该模型是先检查指定名称的类是否已经加载过,如果加载进入内存,不加载直接返回,如果没有加载过,判断是否有父类加载器,如果拥有父类加载器,那么将会直接将权利移交给父类,由父类代理当前类进行加载该类。或者是调用 C ++ 的 bootstrap 类加载器来加载该类最后如果三者都没有找到类,那么直接调用当前类加载器的 findClass 方法来完成类加载。即,如果需要需要加载自定义的类,那么就需要重写 findClass 方法。
即,如果需要将当前类加载进入,那么就需要重写 findClass 方法,若未找到这几种类,则会自动调用 findClass 方法。
调用过程
先加载父类,若父类未加载,继续调用父类,直到 bootstrap 查看是否已经加载,如果此时都未加载类,那么将会使用自定义的 ClassLoader 然后调用自定义的 ClassLoader 的 findClass 方法,用于将字节码加载进入内存。最后返回该 class 的描述符
栗子
public class Test {
public void helloWorld(){
System.out.println(“me loader” + getClass().getClassLoader().getClass());
// 先调用 getClass 获取当前类的对象的描述,然后再次调用 getClassLoader() 获取加载的父类,再次调用 getClass() 获取加载进入的父类的名称
}
}
此时如果该类这这个项目里的里的话,会由 Application 加载当前应用类下的类。
由类的加载过程可知,当未找到类的时候,会加载类的 ClassLoader 类,此时需要定义一个类,让该类继承 ClassLoader 类,由于该类是 ClassLoader 的子类,此时会自动加载该类,由于该类不在内存当中,所以需要使用 static,让其一开始加载进入内存当中。代码如下
import java.io.FileInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Main {
// 需要使用 static 让其加载进入内存
static class myClassLoader extends ClassLoader{
private String classPath; // 获取当前类的在磁盘中保存的地址
// 通过构造函数将地址注入
public myClassLoader(String classPath){
this.classPath = classPath;
}
// 将文件内容加载进入内存
private byte[] loadByte(String name) throws Exception{
// 获取一个输入流,
FileInputStream fis = new FileInputStream(classPath + “/” + name + “.class”);
// 获取长度
int len = fis.available();
// 定义 byte 数组
byte[] data = new byte[len];
// 加载进入内存
fis.read(data);
// 关闭流
fis.close();
return data;
}
// 重写 findClass 方法,让加载的时候调用 findClass 方法
protected Class<?> findClass(String name) throws ClassNotFoundException{
try{
// 读取文件到数组中
byte[] data = loadByte(name);
// 将字节码加载进入内存当中
return defineClass(name, data, 0, data.length);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {
// 先初始化该类
myClassLoader classLoader = new myClassLoader(“/home/ming”);
// 此时会调用 findClass 加载 Test.class 加载进入内存当中
Class clazz = classLoader.loadClass(“Test”);
// 实例化该类对象
Object obj = clazz.newInstance();
// 获取 clazz 该类方法中名称为 hello,参数为空的方法。
Method helloMethod = clazz.getDeclaredMethod(“helloWorld”, null);
// 调用该方法
// 调用 obj 类中的 helloMethod,参数为空的方法。
helloMethod.invoke(obj, null);
}
}
实验结果
me loaderclass Main$myClassLoader
Process finished with exit code 0
https://www.iming.info/shuang…