您好,登錄后才能下訂單哦!
JVM中深堆和淺堆的認識是怎么樣的,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
一、概念
我們先給出概念,然后再分析。
(1)淺堆表示一個java對象結構所占用內存的大小,這個java對象內部包含了三部分數據:對象頭、實例數據和對齊填充。
(2)深堆表示一個java對象被 GC 回收后,可以真實釋放的內存大小。
如果你有點疑惑,沒關系。對上面出現的那些名詞我們一個一個來解釋。
1、對象頭
一個對象分為三部分:對象頭、實例數據、對齊填充。對象頭又包含了兩部分:標記部分和原始對象引用。
(1)標記部分:包括 hashcode、gc 分代年齡、鎖狀態標志、線程持有鎖、偏向線程鎖id,偏向時間戳,這一部分在32位機器上為 4 byte,64 位機器上為 8byte,一般來說我們的機器都是64位,所以現在默認指的是8個字節。
(2)原始對象引用是對象的指針,通過這個指針找到對象的實例,該數據可以壓縮,32 位機器上為 4 byte,64位機器上為 8byte,jdk8默認開啟壓縮,大小為 4byte。
所以我們可以看到:一個java對象的對象頭大小,沒壓縮的時候是16字節,壓縮時候是12個字節。
2、實例數據
指的就是我們的java對象實例。這個很容易理解。
3、對齊填充
對齊填充要追根其根源,其實是到了計算機系統結構的學科。我在大學的時候學到了對齊填充,和這里是一樣的道理。java中的對象都是以8個字節為單位對齊,所以每一個java對象的大小都是8的整數倍。
4、保留集
對象A能直接或者是間接訪問其他的對象,這些對象集合起來就是A的保留集。當進行垃圾回收的時候,不僅回收A,也會回收保留集中所有的對象。
現在我們理解了這些基本的概念,再回過頭來好好地看看,深堆和淺堆到底是什么?
淺堆指對象本身占用的內存,不包括其內部引用對象的大小。一個對象的深堆指只能通過該對象訪問到的(直接或間接)所有對象的淺堆之和,即對象被回收后,可以釋放的真實空間。在《實戰java虛擬機》中,使用了一個案例,在這里引用一下:
A引用了對象C,D,對象B引用了對象C,E。
對象A引用了C和D,對象B引用了C和E。那么對象A的淺堆大小只是A本身,不含C和D,而A的實際大小為A、C、D三者之和。
而A的深堆大小為A與D之和,由于對象C還可以通過對象B訪問到,因此不在對象A的深堆范圍內。
我們再舉一個例子來分析:1到100,被3整除的數可以送給對象A,被5整除的可以送給對象B。那么在程序退出時候,進行垃圾回收,此時對象A的的深堆肯定小于33,對象B的深堆肯定小于20,這是因為存在像15、30這樣的數,既可以被3整除也可以被5整除,屬于三不管對象。
代碼就不再演示了,最后的結果還是使用MAT工具進行分析一下。
看完上述內容,你們掌握JVM中深堆和淺堆的認識是怎么樣的的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。