java动态加载
java的类加载机制,不会设定加载二进制字节码流的形式。但是默认的三大加载器只会加载标准的class文件,如果我们需要自己加载自定义的二进制字节码流,就需要自定义类加载器
-
- 类加载器
package com.controller;
import java.io.*;
public class MyClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = loadClassData(name);
if (classData == null) {
throw new ClassNotFoundException();
} else {
return defineClass(name, classData, 0, classData.length);
}
}
private byte[] loadClassData(String name) {
File file = new File("D:\\project\\src\\main\\java\\" + name.replace('.',File.separatorChar) + ".class");
try {
FileInputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int buffersize = 1024;
byte[] bytes = new byte[buffersize];
int length = -1;
while ((length = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, length);
}
return outputStream.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
MyClassLoader myClassLoader = new MyClassLoader();
Class<?> aClass = myClassLoader.loadClass("com.controller.Test");
Object o = aClass.newInstance();
System.out.println(o.getClass().getClassLoader());
}
}
-
- 测试类
public class Test {
static {
System.out.println("test2.....");
}
}
-
- 首将test转为class文件,再运行类加载器,实现动态加载
- 首将test转为class文件,再运行类加载器,实现动态加载
双亲委派机制
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
calssload 源码分析
public Class<?> loadClass(String name)throws ClassNotFoundException {
return loadClass(name, false);
}
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 {
//如果不存在父类加载器,就检查是否是由启动类加载器加载的类,通过调用本地方法native Class findBootstrapClass(String name)
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// 如果父类加载器和启动类加载器都不能完成加载任务,才调用自身的加载功能
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}