日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自定义类加载器_jvm超详细探索自定义类加载器(值得收藏)

發布時間:2024/10/12 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自定义类加载器_jvm超详细探索自定义类加载器(值得收藏) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原創:魯班學院子牙老師 微信公眾號搜索啟明南

如果你想看懂本篇文章,需要你對類加載器有一定的了解。如JVM自帶的類加載器、雙親委派、自定義類加載器、類加載每個階段做了什么……如果你對這些知識還有夾生的地方,建議先去補充一下,不然只能達到勸退的效果。

jvm調優視頻地址:https://www.ixigua.com/i6845139758574731787/

在平時開發中,很少會去自定義類加載器,所以以前對這塊也只是了解。如今作為一名老師,自然需要對每個重要知識點達到顆粒劑認知。在研究這塊知識點時,發現這塊知識點并不是我想的那么簡單,而是存在著很多很多容易產生錯誤認知的地方以及不太容易理解的地方。為了詳盡搞情況這些知識點,寫了很多代碼測試,寫點文章記錄下。

后面的自定義類加載器代碼測試時都加載這個類

package com.qimingnan.classload;class Classloader_1_A {}

測試代碼較多,文章中我只貼核心部分。相關的代碼需要的童鞋可關注后私信:課堂演示代碼

JVM自帶的類加載器

jvm自帶的類加載器相信大多數童鞋都知道,這邊我也只是打算稍微提一下,因為關于這塊的認識,很多童鞋也是存在誤區的。

JVM自帶的類加載器有三個:引導類加載器、擴展類加載器、應用類加載器。這三者之間是邏輯上的父子關系,通過parent指針關聯。不要錯誤的理解成一種繼承關系,看下openjdk源碼就知道了,啟動類加載器是純C++編寫的,擴展類加載器、應用類加載器都是繼承自類URLClassLoader。

JVM自帶的三個類加載器在運行期都只有一個實例,但是自定義類加載器你可以創建無數個。但是建議越少越好,會帶來碎片化問題。

為什么說會有碎片化問題呢?這跟JVM的處理機制有關。不同的類加載器加載的類在元空間中是如何存儲的呢?每個加載器在元空間中都能獲得一份獨有的空間,不同的類加載器加載的類都是存放在這個空間中。這就解釋了同一個類,如果同一個類加載器去加載只會加載一次,多個類加載器去加載就會加載多次。關于這個空間可能童鞋們又有很多問題,如這個空間初始多大?引用存放在哪?碎片問題如何解決?這些問題后面寫文章分享或在VIP課上揭曉。

自定義類加載器

想自定義一個類加載器是一件很簡單的事情,繼承類ClassLoader就可以了。但現實中,關于自定義類加載器,還是有很多細節值得我們去細細品味的。

一、只繼承類ClassLoader,不override任何方法,這樣的類加載器能否正常運行。上代碼

public class Classloader_4 extends ClassLoader { public static void main(String[] args) { Classloader_4 classloader = new Classloader_4(); try { Class> clazz = classloader.loadClass("com.qimingnan.classload.Classloader_1_A"); Object obj = clazz.newInstance(); System.out.println(obj); } catch (Exception e) { e.printStackTrace(); } } @Override protected Class> findClass(String className) throws ClassNotFoundException { System.out.println("Classloader_2 findClass"); return null; }}

因為雙親委派機制,自定義類加載器加載類Classloader_1時會將這個加載請求依次上拋給引導類加載器、擴展類加載器、應用類加載器。引導類加載器、擴展類加載器肯定加載不到這個類的。如果AppClassLoader能加載類Classloader_1則完成加載;如果AppClassLoader加載不到,就會由自定義的類加載器Classloader_4 去加載,根據函數調用鏈,最終會調用findClass方法。

二、如何讓自定義的類加載器能夠加載到類Classloader_1,上代碼

public static void main(String[] args) { Classloader_2 classloader = new Classloader_2(); classloader.setFilepath("/home/ziya/Documents/java-text/"); ……}@Overrideprotected Class> findClass(String className) throws ClassNotFoundException { System.out.println("Classloader_2 findClass"); byte[] data = getData(className.replace('.', '/')); return defineClass(className, data, 0, data.length);}private byte[] getData(String name) { File file = new File(filepath + name + SUFFIX); …… return null;}

findClass調用getData方法根據class文件的絕對路徑將class文件讀入內存,然后調用defineClass方法將字節碼文件轉為Class對象并返回。

三、前面有說每個類加載器在元空間中都會分得一塊獨有的空間,上代碼證明下

public class Classloader_4 extends ClassLoader { public static void main(String[] args) throws Exception { Classloader_4 classloader1 = new Classloader_4(); Class> clazz1 = classloader1.loadClass("com.qimingnan.classload.Classloader_1_A"); System.out.println("clazz1 hashcode: " + clazz1.hashCode()); Classloader_4 classloader2 = new Classloader_4(); Class> clazz2 = classloader2.loadClass("com.qimingnan.classload.Classloader_1_A"); System.out.println("clazz2 hashcode: " + clazz2.hashCode()); } ……}

運行結果:

clazz1 hashcode: 460141958clazz2 hashcode: 460141958

hashcode即Class對象的內存地址,可以看到兩個類加載器返回的是同一個Class對象。為什么會這樣呢?因為并非是由這兩個類加載器去加載的,而是由兩個類加載器的父類加載器AppClassLoader加載的。如果是由這兩個類加載器加載呢?看結果:

Classloader_4 findClassclazz1 hashcode: 1956725890Classloader_4 findClassclazz2 hashcode: 21685669

可以看到,因為是兩個不同的類加載器,返回的Class對象的地址也是不一樣的。這也證明了不同的類加載器有其獨享的內存區域。

測試思路:讓AppClassLoader加載不到類Classloader_1_A即可。我是將classes目錄下的class文件刪掉了。刪掉后如果后面不會再生成,執行下maven clean后重試。

結語

本文討論了自定義類加載器的四種情況的細節:

  • 使用一個自定義類加載器去加載類,該加載器的父類加載器也能加載到這個類
  • 使用一個自定義類加載器去加載類,該加載器的父類加載器無法加載到這個類
  • 使用多個自定義類加載器去加載類,加載器的父類加載器也能加載到這個類
  • 使用多個自定義類加載器去加載類,加載器的父類加載器無法加載到這個類
  • 這四種情況就包含了所有的場景嗎?當然沒有!比如多個自定義類加載器之間存在父子關系又有哪些不同。但是萬變不離其宗,這四種情況是最基礎的情況,深刻理解這四種情況,后續接觸到其他情況就能舉一反三理解之。建議看完文章的童鞋實踐實踐,絕知此事要躬行。

    jvm調優視頻:https://www.ixigua.com/i6845139758574731787/

    總結

    以上是生活随笔為你收集整理的自定义类加载器_jvm超详细探索自定义类加载器(值得收藏)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。