- 對象頭存放位置源譬、格式
-
對象頭包含 2 部分梯轻,如果有數(shù)組則包含第 3 部分記錄數(shù)組長度
object header -
Mark Word 根據(jù)虛擬機(jī)是 32 / 64 位占用不同的長度 [詳見參考.3]
object header demomark word -
輕量鎖-鎖定
- 當(dāng)前線程的棧幀中建立一個 Lock Record 的空間
- 復(fù)制對象頭的 Mark Word 到該空間 (Displaced Mark Word)
- CAS 操作更新對象頭的 Mark Word 為該空間的指針
- CAS 成功則獲取到該對象的鎖,鎖標(biāo)記為
00
吸祟;否則需要競爭,鎖膨脹為重量鎖炒刁,鎖標(biāo)記為10
- Lock Record 跟蹤當(dāng)前執(zhí)行方法鎖定的對象(遍歷線程棧找出被鎖對象)
-
輕量鎖-解鎖
- CAS 操作將棧幀中的 Displaced Mark Word 放回對象頭的 Mark Word
- CAS 失敗則出現(xiàn)競爭舞萄,說明有其他線程嘗試獲取該鎖眨补,則會在釋放鎖的同時,喚醒被掛起的線程
-
參考
-
堆的劃分
新生代倒脓、老年代撑螺,新生代里面有 Eden 空間、 From Survivor 空間把还、To Survivor 空間实蓬;
從內(nèi)存分配角度看,會在新生代 Eden 空間劃分出多個 線程私有的分配緩沖區(qū)(Thread Local Allocation Buffer吊履,TLAB)安皱,默認(rèn)占用 1% -
參數(shù)調(diào)優(yōu)
打印 GC 日志:
-XX:+PrintGCDetails
,分析 GC 各階段內(nèi)存情況艇炎,調(diào)整對應(yīng)參數(shù)(如 servivor 區(qū)的比例酌伊、大對象進(jìn)入老年代的閾值、對象年齡閾值缀踪、堆空閑比例居砖、垃圾回收期的選擇、CMS之后整理碎片 等)并定位問題 -
對象逃逸 / 逃逸分析
基本行為就是分析對象動態(tài)作用域:當(dāng)一個對象在方法里面被定義后驴娃,可能被外部方法引用
- 方法逃逸:對象作為調(diào)用參數(shù)傳遞到其他方法中
- 線程逃逸:對象可在其他線程中訪問
針對不會逃逸的對象進(jìn)行的運(yùn)行期優(yōu)化:
-
棧上分配
如果確定一個對象不會逃逸奏候,那么可以直接在棧上分配內(nèi)存,對象占用的空間可歲棧幀出棧而銷毀唇敞;一般應(yīng)用中蔗草,不會逃逸的局部對象所占比例很大,如果能在站上分配疆柔,大量的對象會隨著方法的結(jié)束自動銷毀咒精,減小了垃圾回收的壓力;
缺點(diǎn):不能保證逃逸分析的性能收益必定高于其消耗旷档,可能出現(xiàn)效果不穩(wěn)定的情況
引出另一個問題:對象一定放在堆里面么模叙?
同步消除,沒有逃逸即其他線程無法訪問鞋屈,即不存在同步問題
-
標(biāo)量替換
標(biāo)量(Scalar)是指無法再分解的數(shù)據(jù)(int, long 等)范咨;相反如果可以分解則稱為聚合量(Aggregate),如對象谐区;
將對象使用到的成員變量恢復(fù)到原始類型來訪問就叫做標(biāo)量替換湖蜕;
如果逃逸分析證明一個對象不會被外部訪問切可別拆散的話,那么程序執(zhí)行時可能不會創(chuàng)建這個對象宋列,而直接創(chuàng)建若干個使用到的成員變量來代替(直接在棧上分配和讀寫)
參考:
- Java 中的逃逸分析和 TLAB 以及 Java 對象分配
- 深入理解 Java 虛擬機(jī) 11.3.5 逃逸分析
- wiki