Java 物件分配流程
我們這裡不考慮棧上分配,這些會在 JIT 的章節詳細分析,我們這裡考慮的是無法棧上分配需要共享的物件。
對於 HotSpot JVM 實現,所有的 GC 演算法的實現都是一種對於堆記憶體的管理,也就是都實現了一種堆的抽象,它們都實現了介面 CollectedHeap。當分配一個物件堆記憶體空間時,在 CollectedHeap 上首先都會檢查是否啟用了 TLAB,如果啟用了,則會嘗試 TLAB 分配;如果當前執行緒的 TLAB 大小足夠,那麼從執行緒當前的 TLAB 中分配;如果不夠,但是當前 TLAB 剩餘空間小於最大浪費空間限制,則從堆上(一般是 Eden 區) 重新申請一個新的 TLAB 進行分配。否則,直接在 TLAB 外進行分配。TLAB 外的分配策略,不同的 GC 演算法不同。例如G1:
- 如果是 Humongous 物件(物件在超過 Region 一半大小的時候),直接在 Humongous 區域分配(老年代的連續區域)。
- 根據 Mutator 狀況在當前分配下標的 Region 內分配
TLAB 慢分配與 TLAB 外分配
重新申請一個 TLAB 進行分配,是 TLAB 慢分配,不在 TLAB 分配被稱為 TLAB 外分配。我們可以通過 JFR 來監控 TLAB 慢分配或者 TLAB 外分配事件。也就是jdk.ObjectAllocationOutsideTLAB
與jdk.ObjectAllocationInNewTLAB
這兩個事件。
jdk.ObjectAllocationOutsideTLAB
和 jdk.ObjectAllocationInNewTLAB
這兩個事件在default.jfc
中( JFR 預設事件採集配置)是沒有開啟採集的:
<event name="jdk.ObjectAllocationInNewTLAB">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>
<event name="jdk.ObjectAllocationOutsideTLAB">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
</event>
一般的,採集這兩個事件,是需要連著堆疊一起採集,但是無法通過持續時間(因為這個事件沒有持續時間這一概念)限制採集哪些,也就是隻要開啟就是全部採集,所以不建議長期開啟這個採集。而是通過一些其他的監控項,按照需要,動態開啟這個採集一段時間,之後關閉並 dump 出 JFR 檔案用於分析。
每日一刷,輕鬆提升技術,斬獲各種offer: