在上一篇博客中寫到雙親委派機制.傳送門
瞭解完雙親委派機制那麼對JVM類加載器原理有一定的瞭解,那麼書寫定義類加載加載器就不會太難了.主要是重寫ClassLoader中findClass方法
這個方法主要是根據包名查找class文件
package com.bonc.jvm;
import java.io.FileInputStream;
import java.lang.reflect.Method;
/**
* @Classname MyClassLoadTEst
* @Description TODO
* @Date 2020/6/14 16:31
* @Created by sz
*/
public class MyClassLoadTest {
static class MyClassLoad extends ClassLoader{
private String classPath;
public MyClassLoad(String classPath){
this.classPath=classPath;
}
private byte[] loadByte(String name) throws Exception {
name = name.replaceAll("\\.", "/");
FileInputStream fis = new FileInputStream(classPath + "/" + name
+ ".class");
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] data = loadByte(name);
//defineClass將一個字節數組轉爲Class對象,這個字節數組是class文件讀取後最終的字節 數組。
return defineClass(name, data, 0, data.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}
}
public static void main(String[] args) throws Exception {
MyClassLoad classLoader = new MyClassLoad("D:/tmp");
Class clazz = classLoader.loadClass("com.bonc.jvm.User1");
Object obj = clazz.newInstance();
Method method = clazz.getDeclaredMethod("print", null);
method.invoke(obj,null);
System.out.println(clazz.getClassLoader().getClass().getName());
}
}
package com.bonc.jvm;
import java.io.PrintStream;
public class User1
{
private int age;
public void print()
{
System.out.println("自定義ClassLoad");
}
}
運行結果:
執行前提:當前classpath沒有那個class文件
那麼加在自定義加載器之後,整個類加載機制就更新爲
注意:MyClassLoad AppClassLoader ExtClassLoader 之間都不存在繼承關係.只是MyClassLoad 的parent屬性是AppClassLoader 並且AppClassLoader 的parent屬性是ExtClassLoader