欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

自定義類加載器的父類為何是AppClassLoader說明

 更新時間:2022年11月21日 09:26:08   作者:小小少年_  
這篇文章主要介紹了自定義類加載器的父類為何是AppClassLoader說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

首先有一個概念要了解

我們通常說在jdk中,默認有三個類加載器,bootstrapClassLoader、ExtClassLoader、AppClassLoader,我們說前者是后者的父類加載器,但是實際上,這里所謂的父類加載器,并不是Java中的父子類繼承關系,而是說:

  • AppClassLoader中有一個parentClassLoader設置的值是ExtClassLoader
  • ExtClassLoader中的parentClassLoader設置的是bootstrapClassLoader
  • 我們自定義的類加載器,對應的parentClassLoader是AppClassLoader

我們如果自定義一個類加載器,默認設置的父類加載器是AppClassLoader,這個原因是在因為在初始化自定義類加載器的時候,會指定其parentClassLoader為AppClassLoader

Launcher

這個類是jre中用來啟動main()方法的入口,在這個類中,我們著重關注的是初始化構造方法

public Launcher() {
? ? Launcher.ExtClassLoader var1;
? ? try {
? ? ?? ?// 初始化extClassLoader
? ? ? ? var1 = Launcher.ExtClassLoader.getExtClassLoader();
? ? } catch (IOException var10) {
? ? ? ? throw new InternalError("Could not create extension class loader", var10);
? ? }

? ? try {
? ? ?? ?// 初始化appClassLoader,這里的這個賦值是比較重要的
? ? ? ? this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
? ? } catch (IOException var9) {
? ? ? ? throw new InternalError("Could not create application class loader", var9);
? ? }

? ? Thread.currentThread().setContextClassLoader(this.loader);
? ? String var2 = System.getProperty("java.security.manager");
? ? if (var2 != null) {
? ? ? ? SecurityManager var3 = null;
? ? ? ? if (!"".equals(var2) && !"default".equals(var2)) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? var3 = (SecurityManager)this.loader.loadClass(var2).newInstance();
? ? ? ? ? ? } catch (IllegalAccessException var5) {
? ? ? ? ? ? } catch (InstantiationException var6) {
? ? ? ? ? ? } catch (ClassNotFoundException var7) {
? ? ? ? ? ? } catch (ClassCastException var8) {
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? var3 = new SecurityManager();
? ? ? ? }

? ? ? ? if (var3 == null) {
? ? ? ? ? ? throw new InternalError("Could not create SecurityManager: " + var2);
? ? ? ? }

? ? ? ? System.setSecurityManager(var3);
? ? }
}

這個構造方法中,我目前所了解到的,就是初始化了AppClassLoader和ExtClassLoader,并且,和這篇博客相關的,我們只需要關心this.loader這個全局變量,這個全局變量存放的是AppClassLoader的對象信息

構造一個自定義類加載器

我們要自定義一個類加載器,只需要繼承classLoader,并重寫findClass()方法即可

class MyClassLoader extends ClassLoader {

? ? private String loadPath;

? ? public String getLoadPath() {
? ? ? ? return loadPath;
? ? }

? ? public void setLoadPath(String loadPath) {
? ? ? ? this.loadPath = loadPath;
? ? }

? ? @Override
? ? protected Class<?> findClass(String name) throws ClassNotFoundException {
? ? ? ? try {
? ? ? ? ? ? byte[] bytes = loadByte(name);
? ? ? ? ? ? return defineClass(name, bytes, 0, bytes.length);
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? System.out.println(e.getMessage());
? ? ? ? }
? ? ? ? return null;
? ? }

? ? private byte[] loadByte(String className) throws Exception {
? ? ? ? className = className.replaceAll("\\.", "/");
? ? ? ? FileInputStream fileInputStream = new FileInputStream(loadPath + "/" + className + ".class");
? ? ? ? int available = fileInputStream.available();
? ? ? ? byte[] data = new byte[available];
? ? ? ? fileInputStream.read(data);
? ? ? ? fileInputStream.close();
? ? ? ? return data;
? ? }
}

那么,我在使用的時候,只需要調用new MyClassLoaderTest()即可

new MyClassLoaderTest()

我們說,自定義的類解析器對應的parentClassLoader,就是在空參構造函數中被賦值的

因為MyClassLoaderTest繼承了ClassLoader,所以,會調用到ClassLoader的空參構造函數

protected ClassLoader() {
? ? this(checkCreateClassLoader(), getSystemClassLoader());
}
private ClassLoader(Void unused, ClassLoader parent) {
? ? this.parent = parent;
? ? if (ParallelLoaders.isRegistered(this.getClass())) {
? ? ? ? parallelLockMap = new ConcurrentHashMap<>();
? ? ? ? package2certs = new ConcurrentHashMap<>();
? ? ? ? domains =
? ? ? ? ? ? Collections.synchronizedSet(new HashSet<ProtectionDomain>());
? ? ? ? assertionLock = new Object();
? ? } else {
? ? ? ? // no finer-grained lock; lock on the classloader instance
? ? ? ? parallelLockMap = null;
? ? ? ? package2certs = new Hashtable<>();
? ? ? ? domains = new HashSet<>();
? ? ? ? assertionLock = this;
? ? }
}

我們會發(fā)現(xiàn),parentClassLoader就是getSystemClassLoader()返回的,

java.lang.ClassLoader#getSystemClassLoader
?? ?java.lang.ClassLoader#initSystemClassLoader


// 這個方法中的其他變量我們可以暫時先不關心,我們看到有獲取到一個Launcher對象
private static synchronized void initSystemClassLoader() {
? ? if (!sclSet) {
? ? ? ? if (scl != null)
? ? ? ? ? ? throw new IllegalStateException("recursive invocation");
? ? ? ? sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
? ? ? ? if (l != null) {
? ? ? ? ? ? Throwable oops = null;
? ? ? ? ? ? // 在這里調用其getClassLoader()方法,將返回的值,賦值給scl,而這個scl就是入參中的parent
? ? ? ? ? ? scl = l.getClassLoader();
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? scl = AccessController.doPrivileged(
? ? ? ? ? ? ? ? ? ? new SystemClassLoaderAction(scl));
? ? ? ? ? ? } catch (PrivilegedActionException pae) {
? ? ? ? ? ? ? ? oops = pae.getCause();
? ? ? ? ? ? ? ? if (oops instanceof InvocationTargetException) {
? ? ? ? ? ? ? ? ? ? oops = oops.getCause();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (oops != null) {
? ? ? ? ? ? ? ? if (oops instanceof Error) {
? ? ? ? ? ? ? ? ? ? throw (Error) oops;
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? // wrap the exception
? ? ? ? ? ? ? ? ? ? throw new Error(oops);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? sclSet = true;
? ? }
}

這里的getClassLoader()返回的就是上面我說明的,需要特別關注的this.classLoader這個全局變量

scl是從l.getClassLoader()這個方法獲取到的結果,那我們看下這個方法

sun.misc.Launcher#getClassLoader
public ClassLoader getClassLoader() {
? ? ? ? return this.loader;
}

可以看到,這里的getClassLoader,就是博客上面 Launcher 這個方法中賦值的this.loader;

所以,通過上面的代碼,可以發(fā)現(xiàn),我們自定義的類解析器,是在初始化的時候,指定了parent為AppClassLoader

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 完美解決MybatisPlus插件分頁查詢不起作用總是查詢全部數據問題

    完美解決MybatisPlus插件分頁查詢不起作用總是查詢全部數據問題

    這篇文章主要介紹了解決MybatisPlus插件分頁查詢不起作用總是查詢全部數據問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • 手動模擬JDK動態(tài)代理的方法

    手動模擬JDK動態(tài)代理的方法

    這篇文章主要介紹了手動模擬JDK動態(tài)代理的方法,幫助大家更好的了解和學習Java 代理的相關知識,感興趣的朋友可以了解下
    2020-11-11
  • 實例解析Java設計模式編程中的適配器模式使用

    實例解析Java設計模式編程中的適配器模式使用

    本篇文章主要通過實例對適配器模式進行了詳解,需要的朋友可以參考下
    2017-04-04
  • Java基于代理模式解決紅酒經銷問題詳解

    Java基于代理模式解決紅酒經銷問題詳解

    這篇文章主要介紹了Java基于代理模式解決紅酒經銷問題,詳細描述了代理模式的概念、原理并結合實例形式分析了java基于代理模式解決紅酒經銷問題的相關步驟、實現(xiàn)方法與操作注意事項,需要的朋友可以參考下
    2018-04-04
  • 關于@Scheduled參數及cron表達式解釋

    關于@Scheduled參數及cron表達式解釋

    這篇文章主要介紹了關于@Scheduled參數及cron表達式解釋,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Docker?快速部署Springboot項目超詳細最新版

    Docker?快速部署Springboot項目超詳細最新版

    這篇文章主要介紹了Docker?快速部署Springboot項目超詳細最新版的相關資料,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • springboot 接收List 入參的幾種方法

    springboot 接收List 入參的幾種方法

    本文主要介紹了springboot 接收List 入參的幾種方法,本文主要介紹了7種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-03-03
  • idea在運行期間,實現(xiàn)讓修改的頁面實時生效

    idea在運行期間,實現(xiàn)讓修改的頁面實時生效

    這篇文章主要介紹了idea在運行期間,實現(xiàn)讓修改的頁面實時生效問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 如何基于java隨機獲取不重復數值

    如何基于java隨機獲取不重復數值

    這篇文章主要介紹了如何基于java隨機獲取不重復數值,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • IDEA 如何控制編輯左側的功能圖標ICON(操作步驟)

    IDEA 如何控制編輯左側的功能圖標ICON(操作步驟)

    很多朋友被idea左側的圖標不見了這一問題搞的焦頭爛額,不知道該怎么操作,今天小編就交大家如何控制編輯左側的功能圖標 ICON,文字內容不多,主要通過兩張截圖給大家說明,感興趣的朋友一起看看吧
    2021-05-05

最新評論