成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

據(jù)說99.99%的人都會答錯的類加載問題

開發(fā) 開發(fā)工具
首先還是把問題拋給大家,這個問題也是我廠同學(xué)在做一個性能分析產(chǎn)品的時候碰到的一個問題。

概述

首先還是把問題拋給大家,這個問題也是我廠同學(xué)在做一個性能分析產(chǎn)品的時候碰到的一個問題。

同一個類加載器對象是否可以加載同一個類文件多次并且得到多個Class對象而都可以被java層使用嗎?

請仔細(xì)注意上面的描述里幾個關(guān)鍵的詞:

  • 同一個類加載器:意味著不是每次都new一個類加載器對象,我知道有些對類加載器有點理解的同學(xué)肯定會想到這點。我們這里強調(diào)的是同一個類加載器對象去加載。
  • 同一個類文件:意味著類文件里的信息都一致,不存在修改的情況,至少名字不能改。因為有些同學(xué)會鉆空子,比如說拿到類文件然后修改名字啥的,哈哈。
  • 多個Class對象:意味著每次創(chuàng)建都是新的Class對象,并不是返回同一個Class對象。
  • 都可以被java層使用:意味著Java層能感知到,或許對我公眾號關(guān)注挺久的同學(xué)看過我的一些文章,知道我這里說的是什么,不知道的可以翻翻我前面的文章,這里賣個關(guān)子,不直接告訴你哪篇文章,稍微提示一下和內(nèi)存GC有關(guān)。

雖然有些標(biāo)題黨的意思,不過我覺得標(biāo)題里的99.99%說得應(yīng)該不夸張,這個比例或許應(yīng)該更大,不過還是請認(rèn)真作答,不要隨便選,我知道肯定有人會隨便選的,哈哈。

正常的類加載

這里提正常的類加載,也是我們大家理解的類加載機制,不過我稍微說得深一點,從JVM實現(xiàn)角度來說一下。在JVM里有一個數(shù)據(jù)結(jié)構(gòu)叫做SystemDictonary,這個結(jié)構(gòu)主要就是用來檢索我們常說的類信息,這些類信息對應(yīng)的結(jié)構(gòu)是klass,對SystemDictonary的理解,可以認(rèn)為就是一個Hashtable,key是類加載器對象+類的名字,value是指向klass的地址。這樣當(dāng)我們?nèi)我庖粋€類加載器去正常加載類的時候,就會到這個SystemDictonary中去查找,看是否有這么一個klass可以返回,如果有就返回它,否則就會去創(chuàng)建一個新的并放到結(jié)構(gòu)里,其中委托類加載過程我就不說了。

那這么一說看起來不可能出現(xiàn)同一個類加載器加載同一個類多次的情況。

正常情況下也確實是這樣的。

奇怪的現(xiàn)象

然而我們從java進程的內(nèi)存結(jié)構(gòu)里卻看到過類似這樣的一些現(xiàn)象,以下是我們性能分析產(chǎn)品里的部分截圖:

在這個現(xiàn)象里,名字為java.lang.invoke.LambdaForm$BMH的類有多個,并且其類加載器都是BootstrapClassLoader,也就是同一個類加載器居然加載了同一個類多次。這是我們的分析工具有問題嗎?顯然不是,因為我們從內(nèi)存里讀到的就是這樣的信息。

現(xiàn)象模擬

上面的這個現(xiàn)象看起來和lambda有一定關(guān)系,不過實際上并不僅僅lambda才有這種情況,我們可以來模擬一下

  1. public static void main(String args[]) throws Throwable { 
  2.        Field f = Unsafe.class.getDeclaredField("theUnsafe"); 
  3.        f.setAccessible(true); 
  4.        Unsafe unsafe = (Unsafe) f.get(null); 
  5.        String filePath = "/Users/nijiaben/AA.class"
  6.        byte[] buffer =getFileContent(filePath); 
  7.        Class<?> c1 = unsafe.defineAnonymousClass(UnsafeTest.class, buffer, null); 
  8.        Class<?> c2 = unsafe.defineAnonymousClass(UnsafeTest.class, buffer, null); 
  9.        System.out.println(c1 == c2); 
  10.    } 

上述代碼其實就是通過Unsafe這個對象的defineAnonymousClass方法來加載同一個類文件兩遍得到兩個Class對象,最終我們輸出為false。這也就是說c1和c2其實是兩個不同的對象。

因為我們的類文件都是一樣的,也就是字節(jié)碼里的類名也是完全一樣的,因此在jvm里的類對象的名字其實也都是一樣的。不過這里我要提一點的是,如果將c1和c2的名字打印出來,會發(fā)現(xiàn)有些區(qū)別,分別會在類名后面加上一個/hashCode值,這個hash值是對應(yīng)的Class對象的hashCode值。這個其實是JVM里的一個特殊處理。

另外你無法通過java層面的其他api,比如Class.forName來獲取到這種class,所以你要保存好這個得到的Class對象才能后面繼續(xù)使用它。

defineAnonymousClass的解說

defineAnonymousClass這個方法比較特別,從名字上也看得出,是創(chuàng)建了一個匿名的類,不過這種匿名的概念和我們理解的匿名是不太一樣的。這種類的創(chuàng)建通常會有一個宿主類,也就是***個參數(shù)指定的類,這樣一來,這個創(chuàng)建的類會使用這個宿主類的定義類加載器來加載這個類,最關(guān)鍵的一點是這個類被創(chuàng)建之后并不會丟到上述的SystemDictonary里,也就是說我們通過正常的類查找,比如Class.forName等api是無法去查到這個類是否被定義過的。因此過度使用這種api來創(chuàng)建這種類在一定程度上會帶來一定的內(nèi)存泄露。

那有人就要問了,看不到啥好處,為啥要提供這種api,這么做有什么意義,大家可以去了解下JSR292。jvm通過InvokeDynamic可以支持動態(tài)類型語言,這樣一來其實我們可以提供一個類模板,在運行的時候加載一個類的時候先動態(tài)替換掉常量池中的某些內(nèi)容,這樣一來,同一個類文件,我們通過加載多次,并且傳入不同的一些cpPatches,也就是defineAnonymousClass的第三個參數(shù), 這樣就能做到運行時產(chǎn)生不同的效果。

主要是因為原來的JVM類加載機制是不允許這種情況發(fā)生的,因為我們對同一個名字的類只能被同一個類加載器加載一次,因而為了能支持動態(tài)語言的特性,提供類似的api來達(dá)到這種效果。

總結(jié)

總的來說,正常情況下,同一個類文件被同一個類加載器對象只能加載一次,不過我們可以通過Unsafe的defineAnonymousClass來實現(xiàn)同一個類文件被同一個類加載器對象加載多遍的效果,因為并沒有將其放到SystemDictonary里,因此我們可以無窮次加載同一個類。這個對于絕大部分人來說是不太了解的,因此大家在面試的時候,你能講清楚我這文章里的情況,相信是一個加分項,不過也可能被誤傷,因為你的面試官也可能不清楚這種情況。

【本文是51CTO專欄作者李嘉鵬的原創(chuàng)文章,轉(zhuǎn)載請通過微信公眾號(你假笨,id:lovestblog)聯(lián)系作者本人獲取授權(quán)】 

戳這里,看該作者更多好文

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2016-10-18 16:30:09

面試float儲格式

2021-04-26 05:35:22

Python內(nèi)置函數(shù)

2024-01-11 08:36:47

懶加載零拷貝前端

2020-05-11 23:18:09

內(nèi)存條CPU插槽

2025-06-26 03:33:00

2021-05-08 15:41:06

計算機互聯(lián)網(wǎng) 技術(shù)

2012-02-14 13:39:57

Java

2017-10-19 16:52:21

網(wǎng)絡(luò)能源

2024-03-08 08:26:25

類的加載Class文件Java

2012-02-09 10:31:17

Java

2021-09-01 14:38:35

鴻蒙HarmonyOS應(yīng)用

2024-03-12 07:44:53

JVM雙親委托機制類加載器

2021-01-06 09:01:05

javaclass

2021-07-05 06:51:43

Java機制類加載器

2025-04-30 07:15:11

2024-09-06 09:37:45

WebApp類加載器Web 應(yīng)用

2025-03-20 08:40:00

TCPUDP端口

2025-02-03 11:27:59

2024-06-24 14:52:50

Android類加載器

2021-01-15 08:37:28

JAR加載
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: www.99精品| 久久久久久免费看 | 九九99精品 | 日本久久精 | 一级片av| 亚洲国产成人av好男人在线观看 | 国产精品夜间视频香蕉 | 欧美v日韩v | 久久综合九色综合欧美狠狠 | 美美女高清毛片视频免费观看 | 精品久久中文字幕 | 久久一二区 | 亚洲aⅴ一区二区 | 黄色网址免费看 | 二区成人 | www国产成人免费观看视频 | 国产高清在线精品 | 亚洲综合首页 | 色爽女 | 99中文字幕| 国产精品久久 | 毛片在线免费 | 精品免费国产视频 | 午夜视频免费在线观看 | 99久久99| 国产69久久精品成人看动漫 | 国产高潮av | 精品欧美乱码久久久久久1区2区 | 国产精久久久久久久 | 亚洲综合在线播放 | 国产精品免费一区二区三区四区 | 蜜月va乱码一区二区三区 | a看片| 91一区二区 | 日日操日日舔 | 午夜精品久久 | 一区二区三区精品视频 | 亚洲精品99999 | 99久久精品国产一区二区三区 | 欧美专区在线 | 国产午夜在线观看 |