成都裝修網(wǎng)站制作價格游戲推廣對接平臺
一、JVM內(nèi)存結(jié)構(gòu)
java的內(nèi)存模型主要分為5個部分,分別是:JVM堆、JVM棧、本地棧、方法區(qū)還有程序計數(shù)器,他們的用途分別是:
- JVM堆:新建的對象都會放在這里,他是JVM中所占內(nèi)存最大的區(qū)域。他又分為新生區(qū)還有老年區(qū),剛new出來的對象放在新生區(qū),等到內(nèi)存不夠的時候,再轉(zhuǎn)移到老年區(qū),這里面有一系列的GC算法,在后面講到。
- JVM棧:他是以線程為單位進行存儲的,所以他只對單個線程是可見的。JVM棧是基于棧的數(shù)據(jù)結(jié)構(gòu)來存儲的,每一個棧內(nèi)元素是一個棧幀,一個方法被調(diào)用,就生成一個棧幀,棧幀里面保存著:局部變量表、操作棧、動態(tài)鏈接還有方法返回地址信息。
- 本地方法棧:jvm可以調(diào)用本地方法,通過JNI方法,這個區(qū)域就是用來保存本地調(diào)用的。
- 本地方法區(qū)(Method Area):本地方法區(qū)里面有方法常量池、保存類信息、保存方法信息的數(shù)據(jù)結(jié)構(gòu),在GC過程中,這里也是永久代數(shù)據(jù)保存的地方。
- 程序計數(shù)器:就像CPU的寄存器一樣,他是記錄線程切換時候機器碼的行號和偏移量的,等方法回調(diào)能夠正常回到方法。
二、JMM內(nèi)存模型
Java的內(nèi)存模型決定了線程間的通信方式,JMM的模型是由主存和本地內(nèi)存構(gòu)成,兩個線程想要正常通行需要將本地內(nèi)存中的變量刷到主存中,另一個線程才能正確讀取得到,這個也是volitile關(guān)鍵詞的原理所在。
JMM模型決定了線程見的通信,由于線程內(nèi)的變量首先會存儲在本地內(nèi)存中,如果需要線程間通信,需要寫入主存中,供其他線程讀取。
由于JVM在執(zhí)行程序時會產(chǎn)生重排序,所有需要引入volitile等關(guān)鍵詞。
三、GC算法
1.可達性算法
1.1.引用計數(shù)算法
原理:對每個對象的引用計數(shù),引用了則+1,釋放了則-1;
1.2.GC root算法
給定一個GC root的集合的引用作為根出發(fā), 通過引用關(guān)系遍歷對象圖,能被遍歷到的(可達到的)對象就判定為存活, 其余對象(也就是沒有被遍歷到的)就自然被判定為死亡。
可以做GC root的是:
- 虛擬機棧(方法)中引用的對象;
- 類變量(靜態(tài)變量)引用的對象;
- 常量引用的對象;
- JNI引用的對象;
2.GC算法
- 復制算法:從根集合開始掃描,將存活的對象復制到另一塊空閑的區(qū)域
- 標記-清除算法:從根集合開始掃描,將存活的對象進行標記,將未標記的空間進行清空
- 標記-壓縮算法:從根集合開始掃描,將存活的對象進行標記和清除,但清除后會將存活對象移動到空閑區(qū)域
對比:基于copy的算法適用于存活對象比較多的GC場景,Mark-sweep適合存活對象較少的場景。
copy based GC算法適合存活對象少的年輕代實現(xiàn),mark-sweep GC算法適合再存活對象多的老年代實現(xiàn)。
四、GC回收器
衡量GC的指標主要是吞吐量、暫停時間。
吞吐量就是CPU用于運行用戶代碼的時間與CPU總消耗時間的比值,即吞吐量 = 運行用戶代碼時間 /(運行用戶代碼時間+垃圾收集時間)。比如:虛擬機總共運行了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。
暫停時間是指一個時間段內(nèi)應用程序線程暫停,讓GC線程執(zhí)行的狀態(tài)。例如,GC期間100毫秒的暫停時間意味著在這100毫秒期間內(nèi)沒有應用程序線程是活動的。
GC回收器的種類:
(1)serial回收器:就是在GC回收的時候工作線程暫定,他是一個串行的回收器;
(2)parallel回收器:就是GC回收器是并發(fā)執(zhí)行的,因此提升了GC的吞吐量,GC過程中會stop the world;
(3)CMS,他的全程是concurrent mark sweep,他的主要優(yōu)勢是在GC回收大多數(shù)時候不需要stop the world;
(4)G1:這個是從JDK7后推出的新的GC,在JDK1.9成為了默認的GC回收器;
1.CMS回收器
CMS是并發(fā)標記清除GC回收器件,其目標是\獲取最短GC停頓時間**,比較符合大型web server項目的使用場景。其GC階段經(jīng)過4個階段:
- 初始標記:初始標記又GC root引用的對象,該過程會引發(fā)STW;
- 并發(fā)標記:這個是不需要STW,并發(fā)標記要回收的對象;
- 重新標記:這個節(jié)點重新標記并發(fā)階段產(chǎn)生的新的要回收的對象;
- 并發(fā)清除;并發(fā)清除標記的要回收的對象;
CMS總結(jié):
- 優(yōu)點:(1)并發(fā)處理效率高;(2)GC的時候不會整體停頓STW,有效降低處理時延。
- 缺點:(1)并發(fā)清理時會降低CPU性能;(2)標記-清理可能會造成大量內(nèi)存碎片;(3)并發(fā)清理階段還會產(chǎn)生垃圾,這種垃圾稱為浮動垃圾,需要下一次GC時才能清理掉。
2.G1回收器
G1回收器會將區(qū)域劃分為region,每個region可以是新生代也可以是老年代,通過控制對region的回收,做到對垃圾回收導致的STW可控。垃圾回收的階段前3個階段和CMS一致,只是最后一個節(jié)點需要通過混合清除來回收新生代和老年代所有的對象:
- 初始標記;標記GC root對象,需要暫停所有用戶線程,該過程會引發(fā)STW;
- 并發(fā)標記;標記GC root可達的對象。
- 最終標記;標記在并發(fā)標記階段產(chǎn)生的需回收對象。
- 篩選回收:對各個Region的回收成本和價值進行排序,根據(jù)用心要求的GC停頓時間來選擇需要GC的Region。
G1總結(jié):
- 優(yōu)點:(1)并發(fā)處理效率高;(2)整體停頓STW的時間可控;(3)新生掉和老年代都分為邏輯上的region,通過GC的復制算法解決內(nèi)存碎片的問題;
- 缺點:引入了Remembered Set來保存內(nèi)存引用信息,所以增加了內(nèi)存占用,所以G1一般在大內(nèi)存的服務(wù)端環(huán)境使用,起步內(nèi)存大小為8G。
3.對比總結(jié)
總結(jié):
- 選擇GC主要考慮的是使用場景,一般嵌入式、內(nèi)存較小的選擇串行GC回收器;
- 對于需求吞吐量大的常見可以選擇并行GC回收器;
- 對于需要時延少的場景可以選擇CMS或者G1回收器;
- CMS回收器整體更側(cè)重增大吞吐量,G1回收器整體是平衡了降低時延和增大吞吐量的要求;
對比:
- serial GC垃圾回收器:serial GC就是串行的GC
- CMS GC垃圾回收器:CMS經(jīng)過(1)初始標記;(2)并發(fā)標記;(3)重新標記;(4)并發(fā)清除;四個階段來完成
- G1 GC垃圾回收期:G1回收會將區(qū)域劃分為region,G1通過(1)初始標記;(2)并發(fā)標記;(3)最終標記;(4)篩選回收;四個階段完成,其中階段四可以計算每個region的耗時來權(quán)衡總耗時,來達到一個平衡??傊厥諘r間可控;
五、對象實例化的過程
首先我們要明白JVM的作用是什么,那就是將.class文件加載到內(nèi)存,并且實例化成對象,在實例化成對象的過程中,需要有哪些操作呢?
在進入這一步之前需要一些前置知識,包括java的54種引用類型和引用在內(nèi)存中的指向等:
java引用的4種類型:
(1)強引用:利用這種方式創(chuàng)建的對象是強應用,Object obj = new Object();這種引用在gc時候不會回收;
(2)軟引用:軟引用在一次gc時候不會回收,之后不一定??
(3)弱引用:弱引用在gc時候一定會被gc;
(4)虛引用:這個用的不多,所以不了解;
棧中引用指向堆中對象:
對象實例化的過程:
(1)在new一個新的對象時,想在本地方法區(qū)中找是否有對于的類元信息,有的話直接調(diào)用相應的classloader進行加載,沒有的話委托給他的父級classloader進行查找,這一步主要是將字節(jié)碼文件通過字節(jié)流的心事加載進來;
(2)為對象分配內(nèi)存空間。由于對象是存儲在堆中,而引用是存在jvm棧中,所以棧中引用需要通過指針的方式只想堆中相應對象,這一步是需要在堆和棧中為對象分配內(nèi)存空間。
(3)設(shè)置默認值和初始化。每一個基本數(shù)據(jù)都有默認值,所以在這一步,需要為變量設(shè)置默認值,同時為成員變量進行初始化操作。
參考資料
- JVM內(nèi)存模型(JVMMM):https://www.huaweicloud.com/zhishi/arc-12588701.html
- JVM之配置參數(shù)詳解和調(diào)優(yōu)總結(jié)(二):https://www.huaweicloud.com/articles/b86de23d6c3d5a161b25b1013a388d8d.html
- jstat命令查看jvm的GC情況 (以Linux為例):http://blog.itpub.net/31543790/viewspace-2657093/
- JVM的架構(gòu)與知識脈絡(luò)圖:https://mp.weixin.qq.com/s/RxzAePMS3ZSnqUY6cj6i7Q
- 《深入理解java虛擬機》
- ClassLoader講的不錯:https://juejin.im/post/5c04892351882516e70dcc9b?utm_source=gold_browser_extension
- 參考資料:https://mp.weixin.qq.com/s?src=11×tamp=1638361551&ver=3470&signature=Gmx2ox8EgDaJsmgMjMMcQb9v87rY-5z9dx*YUJa62leRyG0FI7gXk9eU55UiHMWJ6NYs-7W8GRh2328dZ3mBCbr7O-rFCdNNwYT-8tfe*Ypw8wQ2vpTRfL2nN-28qgBx&new=1
- 弄明白CMS和G1,就靠這一篇了:https://cloud.tencent.com/developer/article/1647637
- JVM:(十六)垃圾回收器:https://blog.csdn.net/sd_960614/article/details/126900380
本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布!