java 詳解類加載器的雙親委派及打破雙親委派
java 詳解類加載器的雙親委派及打破雙親委派
一般的場景中使用Java默認(rèn)的類加載器即可,但有時為了達(dá)到某種目的又不得不實現(xiàn)自己的類加載器,例如為了達(dá)到類庫的互相隔離,例如為了達(dá)到熱部署重加載功能。這時就需要自己定義類加載器,每個類加載器加載各自的類庫資源,以此達(dá)到資源隔離效果。在對資源的加載上可以沿用雙親委派機(jī)制,也可以打破雙親委派機(jī)制。
一、沿用雙親委派機(jī)制自定義類加載器很簡單,只需繼承ClassLoader類并重寫findClass方法即可。如下例子:
①先定義一個待加載的類Test,它很簡單,只是在構(gòu)建函數(shù)中輸出由哪個類加載器加載。
public class Test {
public Test(){
System.out.println(this.getClass().getClassLoader().toString());
}
}
②定義一個TestClassLoader類繼承ClassLoader,重寫findClass方法,此方法要做的事情是讀取Test.class字節(jié)流并傳入父類的defineClass方法即可。然后就可以通過自定義累加載器TestClassLoader對Test.class進(jìn)行加載,完成加載后會輸出“TestLoader”。
public class TestClassLoader extends ClassLoader {
private String name;
public TestClassLoader(ClassLoader parent, String name) {
super(parent);
this.name = name;
}
@Override
public String toString() {
return this.name;
}
@Override
public Class<?> findClass(String name) {
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
is = new FileInputStream(new File("d:/Test.class"));
int c = 0;
while (-1 != (c = is.read())) {
baos.write(c);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return this.defineClass(name, data, 0, data.length);
}
public static void main(String[] args) {
TestClassLoader loader = new TestClassLoader(
TestClassLoader.class.getClassLoader(), "TestLoader");
Class clazz;
try {
clazz = loader.loadClass("test.classloader.Test");
Object object = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、打破雙親委派機(jī)制則不僅要繼承ClassLoader類,還要重寫loadClass和findClass方法,如下例子:
①定義Test類。
public class Test {
public Test(){
System.out.println(this.getClass().getClassLoader().toString());
}
}
②重新定義一個繼承ClassLoader的TestClassLoaderN類,這個類與前面的TestClassLoader類很相似,但它除了重寫findClass方法外還重寫了loadClass方法,默認(rèn)的loadClass方法是實現(xiàn)了雙親委派機(jī)制的邏輯,即會先讓父類加載器加載,當(dāng)無法加載時才由自己加載。這里為了破壞雙親委派機(jī)制必須重寫loadClass方法,即這里先嘗試交由System類加載器加載,加載失敗才會由自己加載。它并沒有優(yōu)先交給父類加載器,這就打破了雙親委派機(jī)制。
public class TestClassLoaderN extends ClassLoader {
private String name;
public TestClassLoaderN(ClassLoader parent, String name) {
super(parent);
this.name = name;
}
@Override
public String toString() {
return this.name;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> clazz = null;
ClassLoader system = getSystemClassLoader();
try {
clazz = system.loadClass(name);
} catch (Exception e) {
// ignore
}
if (clazz != null)
return clazz;
clazz = findClass(name);
return clazz;
}
@Override
public Class<?> findClass(String name) {
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
is = new FileInputStream(new File("d:/Test.class"));
int c = 0;
while (-1 != (c = is.read())) {
baos.write(c);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return this.defineClass(name, data, 0, data.length);
}
public static void main(String[] args) {
TestClassLoaderN loader = new TestClassLoaderN(
TestClassLoaderN.class.getClassLoader(), "TestLoaderN");
Class clazz;
try {
clazz = loader.loadClass("test.classloader.Test");
Object object = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
}
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
如何解決Spring的UnsatisfiedDependencyException異常問題
這篇文章主要介紹了如何解決Spring的UnsatisfiedDependencyException異常問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
淺談Spring Data JPA與MyBatisPlus的比較
本文主要介紹了淺談Spring Data JPA 與 MyBatisPlus的比較2024-08-08
使用 Spring Boot 2.0 + WebFlux 實現(xiàn) RESTful API功能
什么是 Spring WebFlux, 它是一種異步的, 非阻塞的, 支持背壓(Back pressure)機(jī)制的Web 開發(fā)框架.下面通過本文給大家介紹使用 Spring Boot 2.0 + WebFlux 實現(xiàn) RESTful API功能,需要的朋友參考下吧2018-01-01
Java?SE判斷兩個文件內(nèi)容是否相同的多種方法代碼
昨天因為要幫師兄的忙所以看了一下如何判斷兩個文件內(nèi)容是否相同,這里給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于Java?SE判斷兩個文件內(nèi)容是否相同的多種方法,需要的朋友可以參考下2023-11-11
Kotlin中使用Java數(shù)據(jù)類時引發(fā)的Bug解決方式
這篇文章主要介紹了Kotlin中使用Java數(shù)據(jù)類時引發(fā)的一個Bug,本文給大家分享問題解決方式,感興趣的朋友跟隨小編一起看看吧2023-09-09

