最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

終于有人把Java類加載器講清楚了?。?022最新180分鐘超詳細講解)

2022-03-01 17:06 作者:房頂上的鋁皮水塔  | 我要投稿

代碼拆分

通過將處理邏輯的代碼轉移到jar包中,然后通過UrlClassLoader加載某一個位置的URL(jar包所在的位置),加載生成Class對象,然后通過反射的方式調用方法。

代碼混淆

url可以指定一個網絡地址,不一定是一個本地的目錄。jar包中的class文件可以被反編譯。

修改后綴名

(可以反編譯class文件,但是無法反編譯myclass) -> 自定義類加載器

如何自定義一個類加載器

1. 自定義的SalaryClassloader集成SecureClassloader

自定義一個SalaryClassloader用于加載字節(jié)碼的二進制文件:

2. 重寫findClass方法

將這個字節(jié)碼處理為一個byte數組,然后調用defineClass,返回成Class文件。

3. 存在的問題

myclass中的文件內容沒有被改變,可以稍作處理。比如可以生成一種新的class文件,在文件的第一個位置放入一個值(在讀取的時候也要做對應的處理)。這樣可以避免文件被反編譯


實現一個加載Jar包的類加載器

實現一個SalaryJarLoader ,具體的加載邏輯和直接加載文件,讀取文件字節(jié)流的方式類似。


實現熱加載


生成一個Jar文件修改工資計算的方式,但是再次生成Jar文件覆蓋的時候,修改并沒有生效。每次都需要重啟OA系統(tǒng)。


1. 為什么不會生效

因為會從緩存中加載


2.如何修改 :在方法中生成ClassLoader,而不是在最開始執(zhí)行生成一個。這樣就可以每次清除ClassLoader中的緩存

3. 熱加載機制為什么很少使用?

  • 熱加載機制可能出現問題
  • 熱加載機制會產生很多的垃圾對象
  • 默認不會執(zhí)行鏈接


打破雙親委派

出現的問題:如果我們在OASystem的項目中也添加了一個SalaryCaler類,在后續(xù)加載的過程中,不會加載我們定義在jar中的類。

  • 為什么會失?。?/strong>

原因在雙親委派機制上。我們定義的SalaryJarLoader的默認parent是AppClassLoader,AppClassLoader在加載的過程中會首先加載我們定義在OASystem中的SalaryCaler。當SalaryJarLoader在準備加載SalaryCaler時,會在AppClassLoader中找到緩存。這樣一來就不會加載我們定義在jar中的SalaryCaler (這兩個類的全限定名稱是相同的,但是在不同的project中)


解決方式1:通過限定名稱做分支,首先加載自身的SalaryCaler:


解決方式2:解決硬編碼的問題


在上一節(jié)中,雖然可以使用全限定名稱讓SalaryJarLoader優(yōu)先加載定義在jar中的Java文件,而不是首先查看Parent是否加載過。但是使用全限定名稱進行分支判斷的方式存在擴展性的問題。


所以可以重寫ClassLoader#loadClass方法,優(yōu)先執(zhí)行SalaryJarLoader#findClass方法,找到并且返回jar中的Class文件,如果沒有,再去AppClassLoader中加載。

保存多個版本的代碼


使用new創(chuàng)建實例和使用ClassLoader加載一個外部jar包類中的類

會拋出異常:

這是因為兩個類的名字確實相同,但是本質上不是一個類。(可能是為了規(guī)避潛在的類型問題)


只能使用反射的方式:

通過類加載機制構造一個Class對象,然后通過newInstance創(chuàng)建一個Object對象,然后使用Class#getMethod獲取Method,傳入方法名、參數、實例對象 反射調用Method


所以為了同時保存多個版本的代碼,我們首先需要將定義在OASystem同一個project中的SalaryCaler提出,形成一個jar包,并且通過ClassLoader+反射,構造兩個類。



SPI機制完成進一步的優(yōu)化


通過ClassLoader實現的反射的方式可以建立一個Object,但是這種方法不夠優(yōu)雅,我們期望能夠建立一個Interface,然后通過實現接口的方式提供服務。


jdk提供的一種機制。resources下面建立META-INF文件夾,其中再建立services文件夾,在建立一個文件定義加載的內容。

  • Jar中:實現一個SalaryCalerService的實現類

在客戶端(也就是需要通過SPI機制注入服務的OASystem類)定義文件內容:

如果有多個實現類,也需要寫。

因為ServiceLoader#load返回的是當前的interface的所有實現類,所以需要使用迭代器模式。默認會從AppClassLoader中加載,如果需要加載我們ClassLoader,使用load的重載即可。



總結

Java類加載機制的模型:

Java的類加載機制分成三個部分:加載-鏈接-初始化 每一個步驟的主要流程如下:

1. 加載過程 Classloader#loadClass


加載過程也是我們可以干預的過程。在加載器中就體現在ClassLoader#loadClass。

2. 雙親委派機制

雙親委派機制不是說一個加載器是另外一個加載的父節(jié)點,而是像鏈表一樣的持有和傳遞的關系。

通常我們寫的類都會使用AppClassLoader進行加載。



3. 自定義一個類加載器


類似于課程中的方法,如果要自定義一個類加載器,因為我們默認使用了雙親委派機制,loadClass的過程不需要我們考慮,我們需要重寫findClass方法。在findClass方法中我們需要讀取某一個地方的Class字節(jié)流文件。因為這個字節(jié)流文件可能是進行加密處理過,我們可以在這里使用某種方式,還原成原本的Class二進制的byte數組,然后傳遞給defineClass。通過defineClass可以返回一個Class對象。


4. 熱加載機制

如果我們想要臨時修改Class文件的執(zhí)行行為,我們直接修改Class文件行不通。

  • 文件在ClassLoader執(zhí)行時已經讀取了,后面不會再通過這個路徑繼續(xù)讀取
  • 文件已經被讀取到ClassLoader中存在緩存

解決問題1: 在后續(xù)第二次執(zhí)行時,再次讀取Class文件的路徑

解決問題2:需要重新初始化ClassLoader對象


5. 更優(yōu)雅的實現

一個接口存在多個實現類。我們需要借助SPI機制,也就是ServiceLoader接口,對于特定的接口,我們通過META-INF會定義他的實現類名等等。然后我們還可以再ServiceLoader#load時傳入自定義的ClassLoader對象,修改讀取Class實現類的行為。















終于有人把Java類加載器講清楚了?。?022最新180分鐘超詳細講解)的評論 (共 條)

分享到微博請遵守國家法律
朝阳市| 宣恩县| 高雄县| 息烽县| 江达县| 绥德县| 奉贤区| 海阳市| 林芝县| 壤塘县| 阿合奇县| 宁津县| 桦川县| 苍山县| 阿拉善右旗| 姚安县| 巧家县| 元谋县| 乌恰县| 潼关县| 华蓥市| 梓潼县| 大埔县| 无锡市| 墨江| 韶山市| 沈阳市| 天镇县| 女性| 宁陕县| 托克逊县| 湘乡市| 惠东县| 盐亭县| 奉节县| 房产| 修文县| 万盛区| 时尚| 岑巩县| 西丰县|