當前位置:
首頁 > 知識 > Eclipse MAT:淺堆 vs 保留堆

Eclipse MAT:淺堆 vs 保留堆

(給

ImportNew

加星標,提高Java技能)


來自:唐尤華


https://dzone.com/articles/eclipse-mat-shallow-heap-retained-heap


有沒有想要搞清楚淺堆(Shallow Heap)和保留堆(Retained Heap)之間的區別?



Eclipse MAT(內存分析器工具

是功能強大的堆轉儲分析工具,用來調試與內存相關的問題非常方便。 

在 Eclipse MAT 中,會報告兩種類型的對象大小:





  1. 淺堆



  2. 保留堆



在本文中,讓我們一起研究它們之間的區別,並探索它們是如何計算出來的。



圖1 內存中的對象



通過示例可以更輕鬆地掌握新概念。假設應用程序有一個對象模型,如圖1所示:





  • 對象 A 持有對象 B 和 C 的引用



  • 對象 B 持有對象 D 和 E 的引用



  • 對象 C 持有對象 F 和 G 的引用



假設每個對象佔用10個位元組的內存。現在,讓我們基於這個場景開始研究。



1. 淺堆的大小



記住:對象的淺堆指它在內存中的大小。在示例中,每個對象大約佔10個位元組,所以每個對象的淺堆大小是10個位元組,非常簡單。



2. B 的保留堆大小



從圖1可以看到,物體 B 持有對物體 D 和 E 的引用。 因此,如果對象 B 從內存中被垃圾回收,那麼就不再持有對象 D 和 E 的活動引用。這意味著 D 和 E 也可以被垃圾回收。 保留堆指當特定對象被垃圾回收後即將釋放的內存大小。 因此,B 的保留堆大小:

= B 的淺堆大小 + D 的淺堆大小 + E 的淺堆大小
= 10 bytes + 10 bytes + 10 bytes
= 30位元組

因此 B 的保留堆大小為30位元組。



3. C 的保留堆大小



對象 C 包含對象 F 和 G 的引用,因此,如果對象 C 從內存中被垃圾回收,那麼就不再持有對象 F 和 G 的引用。這意味著 F 和 G 也可以被垃圾收集。C 的保留堆大小:


= C 的淺堆大小 + F 的淺堆大小 + G 的淺堆大小
= 10 bytes + 10 bytes + 10 bytes
= 30位元組

因此 C 的保留堆大小也是30位元組。

圖2 對象淺堆的大小和保留堆大小




4. A 的保留堆大小



對象 A 持有對象 B 和 C 的引用,而對象 B 和 C 又持有對象 D、 E、 F 和 G 的引用,因此,如果對象 A 從內存中被垃圾回收,那麼對象 B、 C、 D、 E、 F 和 G 的引用就不存在了。



因此 A 的保留堆大小:


= A 的淺堆大小 + B 的淺堆大小 + C 的淺堆大小 + D 的淺堆大小 + E 的淺堆大小 + F 的淺堆大小 + G 的淺堆大小
= 10 bytes + 10 bytes + 10 bytes + 10 bytes + 10 bytes + 10 bytes + 10 bytes + 10 bytes
= 70位元組

這時我們可以得出結論,A 的保留堆大小為70位元組。



5. D、 E、 F 和 G 的保留堆大小



D 的保留堆大小為10位元組,但這隻包括它們的淺堆大小。這是因為 D 不包含任何其他對象的活動引用。因此,如果 D 被垃圾回收,不會從內存中刪除任何其他對象。同樣道理,E、 F 和 G 的保留堆大小也只有10位元組。


6. 讓我們把研究變得更有趣



現在,讓我們把研究變得更有趣一點,這樣能夠對淺堆和保留堆大小理解得透徹。在示例中讓對象 H 加入對 B 的引用。注意,對象 B 已被對象 A 引用,現在 A 和 H 持有對象 B 的引用。 這種情況下,讓我們研究一下保留堆大小會發生什麼改變。


圖3 對象 B 的新引用



在這種情況下,對象 A 的保留堆大小將減少到40位元組。吃驚不?疑惑嗎?


如果對象 A 被垃圾回收,那麼將對象 C、 F 和 G 的引用將不復存在。因此,只有對象 C、 F 和 G 會被垃圾回收。另一方面,對象 B、 D 和 E 將繼續存在於內存中,因為 H 持有對 B 的活動引用。因此,即使 A 被垃圾回收,B、 D 和 E 也不會從內存中刪除。



因此,A 的保留堆大小為:


= A 的淺堆大小 + C 的淺堆大小 + F 的淺堆大小 + G 的淺堆大小
= 10 bytes + 10 bytes + 10 bytes + 10 bytes
= 40位元組

A 的總保留堆大小將變為40位元組。所有其他對象的保留堆大小保持不變,因為它們的引用沒有變化。



希望本文有助於澄清 Eclipse MAT 中淺堆大小和保留堆大小的計算原理。你還可以考慮使用

HeapHero

這是另一個強大的堆轉儲分析工具,它能計算由於不良編程實踐浪費的內存大小,像如重複對象、過度分配數據結構且利用不足、數據類型定義不佳等。



看完本文有收穫?請轉發分享給更多人


關注「ImportNew」,提升Java技能



喜歡就點「好看」唄~



喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 ImportNew 的精彩文章:

Hystrix是個什麼玩意兒
讓異常處理代碼更健壯

TAG:ImportNew |