新聞中心
java發(fā)展歷史上出現(xiàn)過(guò)很多垃圾回收器,各有各的適應(yīng)場(chǎng)景,不僅僅是開發(fā),作為運(yùn)維也需要對(duì)這方面有一定的掌握,今天簡(jiǎn)單介紹一下java的內(nèi)存布局以及各種垃圾回收器的原理。

成都創(chuàng)新互聯(lián)專注于紫云網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供紫云營(yíng)銷型網(wǎng)站建設(shè),紫云網(wǎng)站制作、紫云網(wǎng)頁(yè)設(shè)計(jì)、紫云網(wǎng)站官網(wǎng)定制、成都小程序開發(fā)服務(wù),打造紫云網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供紫云網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。
JVM內(nèi)存布局
JVM從概念上大致分為6個(gè)(邏輯)區(qū)域:
這6塊區(qū)域按是否被線程共享,可以分為兩大類:
一類是每個(gè)線程所獨(dú)享的:
- PC Register:也稱為程序計(jì)數(shù)器, 記錄每個(gè)線程當(dāng)前執(zhí)行的指令信。eg:當(dāng)前執(zhí)行到哪一條指令,下一條該取哪條指令。
- JVM Stack:也稱為虛擬機(jī)棧,記錄每個(gè)棧幀(Frame)中的局部變量、方法返回地址等。
- Native Method Stack:本地(原生)方法棧,顧名思義就是調(diào)用操作系統(tǒng)原生本地方法時(shí),所需要的內(nèi)存區(qū)域。
上述3類區(qū)域,生命周期與Thread相同,即:線程創(chuàng)建時(shí),相應(yīng)的區(qū)域分配內(nèi)存,線程銷毀時(shí),釋放相應(yīng)內(nèi)存。
另一類是所有線程共享的:
- Heap:即鼎鼎大名的堆內(nèi)存區(qū),也是GC垃圾回收的主站場(chǎng),用于存放類的實(shí)例對(duì)象及Arrays實(shí)例等。
- Method Area:方法區(qū),主要存放類結(jié)構(gòu)、類成員定義,static靜態(tài)成員等。
- Runtime Constant Pool:運(yùn)行時(shí)常量池,比如:字符串,int -128~127范圍的值等,它是Method Area中的一部分。
Heap、Method Area 都是在虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建,虛擬機(jī)退出時(shí)釋放。
總之,程序運(yùn)行時(shí),內(nèi)存中的信息大致分為兩類,一是跟程序執(zhí)行邏輯相關(guān)的指令數(shù)據(jù),這類數(shù)據(jù)通常不大,而且生命周期短;一是跟對(duì)象實(shí)例相關(guān)的數(shù)據(jù),這類數(shù)據(jù)可能會(huì)很大,而且可以被多個(gè)線程長(zhǎng)時(shí)間內(nèi)反復(fù)共用,比如字符串常量、緩存對(duì)象這類。
將這兩類特點(diǎn)不同的數(shù)據(jù)分開管理,體現(xiàn)了軟件設(shè)計(jì)上“模塊隔離”的思想。好比我們通常會(huì)把后端service與前端website解耦類似,也更便于內(nèi)存管理。
GC垃圾回收原理
1. 哪些內(nèi)存區(qū)域需要GC ?
thread獨(dú)享的區(qū)域:PC Regiester、JVM Stack、Native Method Stack,其生命周期都與線程相同(即:與線程共生死),所以無(wú)需GC。線程共享的Heap區(qū)、Method Area則是GC關(guān)注的重點(diǎn)對(duì)象。
2. 常用的GC算法
(1) mark-sweep 標(biāo)記清除法
如上圖,黑色區(qū)域表示待清理的垃圾對(duì)象,標(biāo)記出來(lái)后直接清空。該方法簡(jiǎn)單快速,但是缺點(diǎn)也很明顯,會(huì)產(chǎn)生很多內(nèi)存碎片。
(2) mark-copy 標(biāo)記復(fù)制法
思路也很簡(jiǎn)單,將內(nèi)存對(duì)半分,總是保留一塊空著(上圖中的右側(cè)),將左側(cè)存活的對(duì)象(淺灰色區(qū)域)復(fù)制到右側(cè),然后左側(cè)全部清空。避免了內(nèi)存碎片問題,但是內(nèi)存浪費(fèi)很嚴(yán)重,相當(dāng)于只能使用50%的內(nèi)存。
(3) mark-compact 標(biāo)記-整理(也稱標(biāo)記-壓縮)法
避免了上述兩種算法的缺點(diǎn),將垃圾對(duì)象清理掉后,同時(shí)將剩下的存活對(duì)象進(jìn)行整理挪動(dòng)(類似于windows的磁盤碎片整理),保證它們占用的空間連續(xù),這樣就避免了內(nèi)存碎片問題,但是整理過(guò)程也會(huì)降低GC的效率。
(4) generation-collect 分代收集算法
上述三種算法,每種都有各自的優(yōu)缺點(diǎn),都不完美。在現(xiàn)代JVM中,往往是綜合使用的,經(jīng)過(guò)大量實(shí)際分析,發(fā)現(xiàn)內(nèi)存中的對(duì)象,大致可以分為兩類:有些生命周期很短,比如一些局部變量/臨時(shí)對(duì)象,而另一些則會(huì)存活很久,典型的比如websocket長(zhǎng)連接中的connection對(duì)象,如下圖:
縱向y軸可以理解分配內(nèi)存的字節(jié)數(shù),橫向x軸理解為隨著時(shí)間流逝(伴隨著GC),可以發(fā)現(xiàn)大部分對(duì)象其實(shí)相當(dāng)短命,很少有對(duì)象能在GC后活下來(lái)。因此誕生了分代的思想,以Hotspot為例(JDK 7):
將內(nèi)存分成了三大塊:年青代(Young Genaration),老年代(Old Generation),永久代(Permanent Generation),其中Young Genaration更是又細(xì)為分eden,S0,S1三個(gè)區(qū)。
結(jié)合我們經(jīng)常使用的一些jvm調(diào)優(yōu)參數(shù)后,一些參數(shù)能影響的各區(qū)域內(nèi)存大小值,示意圖如下:
GC主要過(guò)程
下圖引自阿里出品的《碼出高效-Java開發(fā)手冊(cè)》一書,梳理了GC的主要過(guò)程。
分享標(biāo)題:詳解JVM內(nèi)存布局及GC原理,值得收藏
文章URL:http://www.dlmjj.cn/article/djggdci.html


咨詢
建站咨詢
