歡迎光臨
每天分享高質量文章

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技能

喜歡就點「好看」唄~

 

    贊(0)

    分享創造快樂