JVM—對象的創(chuàng)建流程與內(nèi)存分配
創(chuàng)建流程
對象創(chuàng)建的流程圖如下:
對象的內(nèi)存分配方式
內(nèi)存分配的方式有兩種:
- 指針碰撞(Bump the Pointer)
- 空閑列表(Free List)
分配方式 | 說明 | 收集器 |
---|---|---|
指針碰撞(Bump the Pointer) | 內(nèi)存地址是連續(xù)的(新生代) | Serial和ParNew收集器 |
空閑列表(Free List) | 內(nèi)存地址不連續(xù)(老年代) | CMS收集器和Mark-Sweep收集器 |
指針碰撞
指針碰撞示意圖如下:
內(nèi)存分配安全問題:
虛擬機給A線程分配內(nèi)存的過程中,指針未修改,此時B線程同時使用了該內(nèi)存,就會出現(xiàn)問題。
解決方式:
- CAS樂觀鎖:JVM虛擬機采用CAS失敗重試的方式保證更新操作的原子性;
- TLAB (Thread Local Allocation Buffer)本地線程分配緩存,預(yù)分配。
分配主流程
首先從TLAB里面分配,如果分配不到,再使用CAS從堆里面劃分。
對象如何進入老年代
對象進入老年代流程如下:
-
新對象大多數(shù)默認都進入Eden;
-
對象進入老年代的四種情況:
-
年齡太大 MinorGC15次【
-XX:MaxTenuringThreshold
】; -
動態(tài)年齡判斷:MinorGC后會動態(tài)判斷年齡,將符合要求對象移入老年代;
MinorGC之后,發(fā)現(xiàn)Survivor區(qū)中的一批對象的總大小大于了這塊Survivor區(qū)的50%,那么就會將此時大于等于這批對象年齡最大值的所有對象,直接進入老年代。
例子: Survivor區(qū)中有一批對象,年齡分別為年齡1+年齡2+年齡n的多個對象,對象總和大小超過了Survivor區(qū)域的50%,此時就會把年齡n及以上的對象都放入老年代。希望那些可能是長期存活的對象,盡早進入老年代。 比率可以由-XX:TargetsurvivorRatio指定
-
大對象直接進入老年代1M【
-XX:PretenureSizeThreshold
】;(前提是Serial和ParNew收集器)為了避免大對象分配內(nèi)存時的復(fù)制操作降低效率。
避免了Eden和Survivor區(qū)的復(fù)制。
-
MinorGC后存活對象太多無法放入Survivor。
-
空間擔保機制
空間擔保機制:當新生代無法分配內(nèi)存的時候,我們想把新生代的老對象轉(zhuǎn)移到老年代,然后把新對象放入騰空的新生代。此種機制我們稱之為內(nèi)存擔保。
空間擔保流程圖如下:
對象內(nèi)存布局
對象內(nèi)存布局示意圖如下:
對象里的三個區(qū)
堆內(nèi)存中,一個對象在內(nèi)存中存儲的布局可以分為三塊區(qū)域:
堆內(nèi)存中,一個對象在內(nèi)存中存儲的布局可以分為三塊區(qū)域:
-
對象頭(Header) : Java對象頭占8byte。如果是數(shù)組則占12byte。因為JVM里數(shù)組size需要使用4byte存儲。
-
標記字段MarkWord:
-
用于存儲對象自身的運行時數(shù)據(jù),它是synchronized實現(xiàn)輕量級鎖和偏向鎖的關(guān)鍵。
-
默認存儲:對象HashCode、GC分代年齡、鎖狀態(tài)等等信息。
-
為了節(jié)省空間,也會隨著鎖標志位的變化,存儲數(shù)據(jù)發(fā)生變化。
-
-
類型指針KlassPoint:
- 是對象指向它的類元數(shù)據(jù)的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例
- 開啟指針壓縮存儲空間4byte,不開啟8byte。
- JDK1.6+默認開啟
-
數(shù)組長度:如果對象是數(shù)組,則記錄數(shù)組長度,占4個byte,如果對象不是數(shù)組則不存在。
-
對齊填充:保證數(shù)組的大小永遠是8byte的整數(shù)倍。
-
-
實例數(shù)據(jù)(Instance Data):生成對象的時候,對象的非靜態(tài)成員變量也會存入堆空間
-
對齊填充(Padding) :JVM內(nèi)對象都采用8byte對齊,不夠8byte的會自動補齊。
如何訪問一個對象
有兩種方式:
-
句柄:穩(wěn)定,對象被移動只要修改句柄中的地址
-
直接指針:訪問速度快,節(jié)省了一次指針定位的開銷
文章來源:http://www.zghlxwxcb.cn/news/detail-846760.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-846760.html
到了這里,關(guān)于JVM—對象的創(chuàng)建流程與內(nèi)存分配的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!