參考:
一篇文章讀懂Java類加載器
全面解析Java類加載器
類加載器
-
類加載器結(jié)構(gòu):
ClassLoader類是一個抽象類,但卻沒有包含任何抽象方法。
如果要實現(xiàn)自己的類加載器且不破壞雙親委派模型,只需要繼承ClassLoader類并重寫findClass方法。
如果要實現(xiàn)自己的類加載器且破壞雙親委派模型,則需要繼承ClassLoader類并重寫loadClass,findClass方法。
自定義類加載器
- 實現(xiàn)自定義類加載器的三步:
1.繼承ClassLoader
2.重寫findClass()方法
3.調(diào)用defineClass()方法
一個基本的自定義類加載器代碼如下:
/*
* John Han.
* Copyright (c) 2019-2019 All Rights Reserved.
*/
package com.john.learn.basic.class_loader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/*
* 自定義類加載器
* author: john.
* version: CustomClassLoader.java, v 0.1 2019年05月18日 下午5:14 Exp.
*/
public class CustomClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] result = getClassFromCustomPath(name);
if (result == null) {
throw new FileNotFoundException(name);
} else {
// defineClass方法將字節(jié)碼轉(zhuǎn)化為類
return defineClass(name, result, 0, result.length);
}
} catch (Exception e) {
e.printStackTrace();
}
throw new ClassNotFoundException(name);
}
private byte[] getClassFromCustomPath(String name) {
// 從自定義路徑中加載指定類,返回類的字節(jié)碼文件
InputStream in = null;
ByteArrayOutputStream out = null;
String path = "/Users/john/" + name + ".class";
try {
in = new FileInputStream(path);
out = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len = 0;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
return out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
public static void main(String[] args) {
CustomClassLoader customClassLoader = new CustomClassLoader();
try {
Class<?> clazz = Class.forName("One", true, customClassLoader);
Object obj = clazz.newInstance();
// cn.xpleaf.coding.c4.CustomClassLoader@610455d6
System.out.println(obj.getClass().getClassLoader());
} catch (Exception e) {
e.printStackTrace();
}
}
}
