Java內(nèi)存結(jié)構(gòu)和垃圾回收

內(nèi)存結(jié)構(gòu)

java內(nèi)存結(jié)構(gòu)主要有三大區(qū)塊:棧內(nèi)存,堆內(nèi)存,堆外內(nèi)存(直接內(nèi)存)。其中:

1.棧內(nèi)存主要是存放線程的棧信息,每個線程有獨立的線程棧。

2.堆內(nèi)存有元信息區(qū)和對象區(qū),對象區(qū)則采用分代的策略,便于垃圾回收。

3.元信息區(qū)主要存放類信息,靜態(tài)變量信息。

4.此外還有堆外內(nèi)存,這部分內(nèi)存不受垃圾回收器的管理,其內(nèi)存管理自成另一套體系。

所有的內(nèi)存空間之和不能超過物理內(nèi)存,以及操作系統(tǒng)規(guī)定的內(nèi)存限制。

image.png

棧內(nèi)存

每個線程擁有獨立的線程棧。占中存放線程的調(diào)用信息,對象引用,以及基本類型的對象(大小確定的,如int ,short, long, byte, float, double,boolean,char)。

可以通過-Xss 指定每個線程棧的大小,默認(rèn)會使用jdk自帶的大小。

當(dāng)遞歸層數(shù)過多,或者線程的對象應(yīng)用過多,可能造成棧內(nèi)存不足的報錯:StackOverFlowError.

堆內(nèi)存

存放通過new 創(chuàng)建的對象實例。所有線程共享。運行時動態(tài)分配內(nèi)存。jvm會監(jiān)控對象實例的引用狀態(tài)等,并采用垃圾回收機(jī)制,盡可能優(yōu)化堆內(nèi)存的使用,釋放無用的對象實例。

垃圾回收

jvm通過垃圾回收來回收堆和方法區(qū)中的內(nèi)存,基本原理就是找到城中不再被使用的對象,然后回收掉這些對象占用的內(nèi)存。自動回收機(jī)制,以使得程序員擺脫內(nèi)存管理的繁雜事務(wù)。垃圾回收有可達(dá)性檢測,整理無用對象實例,以及分代/分區(qū)思想等內(nèi)容。

可達(dá)性檢測

即檢測對象是否不再被使用。主要有引用計數(shù)和跟蹤計數(shù)兩種。

  1. 引用計數(shù)器記錄對象是否被引用,當(dāng)計數(shù)器為0時,說明對象已經(jīng)不再被使用,可以回收。但是java中的引用關(guān)系非常復(fù)雜,存在循環(huán)引用的情況,因此引用計數(shù)器不適合。

  2. 跟蹤計數(shù):執(zhí)行的時候,從根集合開始掃描對象的引用關(guān)系,從節(jié)點向下搜索,如果一個對象到根集合沒有引用鏈,那么該對象是不可用的。根集合主要值:虛擬機(jī)棧中引用的對象、方法區(qū)中類靜態(tài)屬性引用的休想、方法區(qū)中敞亮引用的對象、本地方法棧中jni引用的對象。

整理策略

  1. 復(fù)制:從根集合中掃描出存活的對象,然后將存活的對象復(fù)制到一塊新的未使用空間。當(dāng)存活對象較少時,比較高效。
  2. 標(biāo)記清除:從根集合開始掃描,標(biāo)記存活的對象。再掃描整個空間未標(biāo)價的對象,然后回收,對象無需移動,高效但是有碎片。
  3. 標(biāo)記壓縮:標(biāo)記形式與“標(biāo)記清除”一樣,但是回收不存在的對象后,會做一次內(nèi)存整理。成本高但是無碎片。

分代、分區(qū)思想

分代和分區(qū)思想,將堆內(nèi)存區(qū)分管理,對不同的區(qū)塊進(jìn)行不同策略的回收機(jī)制,使得生命周期短的對象能夠快速被收回,生命周期長的對象能夠在適當(dāng)?shù)臅r候做統(tǒng)一回收。

年輕代,年老代的設(shè)置即時分代和分區(qū)思想的一種實現(xiàn)。

垃圾回收器

  1. 串行收集器(Serial):指的是使用一個單線程進(jìn)行垃圾收集,工作的時候會暫停其他工作線程。

  2. 并行收集器(Parallel):使用多線程完成垃圾收集,工作的時候會暫停其他工作線程。

  3. CMS收集器:并發(fā)標(biāo)記清除,少量時間會暫停其他工作線程,其余時間與工作線程共同執(zhí)行。

  4. G1收集器:垃圾優(yōu)先收集器,設(shè)計初衷是盡量縮短超大堆(大于4G)時產(chǎn)生的停頓,相對于cms來說內(nèi)存碎片大大降低,但是也會存在可能會造成停頓時間較長。jdk 1.7u4以上可以使用。不過目前線上還沒有使用這種策略。

堆外內(nèi)存

將對象分配到j(luò)ava虛擬機(jī)以外的內(nèi)存,這部分內(nèi)存直接受操作系統(tǒng)管理,可以減少受到垃圾回收對應(yīng)用程序造成的影響。使用java.nio.DirectByteBuffer對象進(jìn)行堆外內(nèi)存的管理和使用。

為什么要有堆外內(nèi)存

減少垃圾回收;加快復(fù)制到遠(yuǎn)程的速度:堆內(nèi)存在flush到遠(yuǎn)程時,會先復(fù)制到直接內(nèi)存,然后再發(fā)送,而堆外內(nèi)存少了復(fù)制這一步。

堆外內(nèi)存的問題

內(nèi)存難以控制

gc觸發(fā)時機(jī)的問題

何時觸發(fā)minor gc

  1. 當(dāng)eden區(qū)分配內(nèi)存,發(fā)現(xiàn)空間不足,jvm就會觸發(fā)minor gc
  2. 程序中調(diào)用Sysetm.gc()

何時觸發(fā)cms gc

  1. 老年代或者持久代已經(jīng)使用的空間達(dá)到設(shè)定的百分比時(CMSInitiatingOccupancyFraction這個設(shè)置old區(qū),perm區(qū)也可以設(shè)置);
  2. JVM自動觸發(fā)(JVM的動態(tài)策略,也就是悲觀策略)(基于之前GC的頻率以及舊生代的增長趨勢來評估決定什么時候開始執(zhí)行),如果不希望JVM自行決定,可以通過-XX:UseCMSInitiatingOccupancyOnly=true來禁用

何時觸發(fā)full gc

  1. 老年代空間不足:java.lang.OutOfMemoryError: java heap space
  2. Perm空間不足:java.lang.OutOfMemoryError: PermGen space
  3. cms gc 時出現(xiàn) promotion failed 和 concurrent mode failure(cms正在進(jìn)行,但是老年代內(nèi)存不足,需要盡快回收老年代的對象)
  4. 統(tǒng)計得到的minor gc 晉升到老年代的平均大小大于老年代的剩余空間
  5. 主動觸發(fā) full gc : 執(zhí)行 jmap -histo:live [pid]

關(guān)于內(nèi)存管理的jvm 參數(shù)設(shè)置

大小

  • -Xms5g 最小堆內(nèi)存
  • -Xmx5g 最大堆內(nèi)存,建議與最小堆內(nèi)存一致,避免jvm動態(tài)調(diào)整
  • -Xmn2g 新生代內(nèi)存
  • -XX:MetaspaceSize=512m jdk8 中元信息的空間大小
  • -XX:MaxMetaspaceSize=512m jdk8 中元信息的最大空間大小
  • -XX:MaxDirectMemorySize=1g 直接內(nèi)存的最大空間,超過空間,會執(zhí)行一次內(nèi)存回收。如果不設(shè)置,會和-Xmx基本差不多,導(dǎo)致直接內(nèi)存和堆內(nèi)存相加超過物理內(nèi)存,報內(nèi)存空間不足的錯誤。
  • -XX:SurvivorRatio=8 eden和suvivor的比例。例如設(shè)置為8,則eden:s0:s1的比例為8:1:1

垃圾回收器策略

  • -XX:+UseConcMarkSweepGC 使用cms(并發(fā)標(biāo)記消除)進(jìn)行老年代的回收,默認(rèn)新生代采用ParNew回收
  • -XX:+UseParallelGC 使用并行
  • -XX:+UseSerialGC 串行g(shù)c

其他

cms相關(guān)的參數(shù)

  • -XX:CMSInitiatingOccupancyFraction=75 內(nèi)存使用率達(dá)到75%后,開始cms收集
  • -XX:+UseCMSInitiatingOccupancyOnly 禁用jvm cms的悲觀策略,僅根據(jù)內(nèi)存使用率來觸發(fā)cms
  • -XX:+UseCMSCompactAtFullCollection cms是消除策略,有內(nèi)存碎片。指定該參數(shù)后,在fgc后會整理碎片。
  • -XX:CMSMaxAbortablePrecleanTime =5000
  • -XX:+CMSClassUnloadingEnabled 方法區(qū)使用cms,允許對類的元數(shù)據(jù)進(jìn)行回收
  • -XX:CMSPermGenSweepingEnabled 方法區(qū)使用cms

gc日志相關(guān)參數(shù)

  • -Xloggc=/gc.log gc日志輸出的地址
  • -XX:+PrintGCDetails 開啟詳細(xì)gc模式
  • -XX:+PrintGCDateStamps 每一行前面加上絕對時間戳
  • -XX:+HeapDumpOnOutOfMemoryError 內(nèi)存溢出時輸出堆日志
  • -XX:HeapDumpPath=/heap.hprof 堆日志輸出地址

參考資料:
[1]【原】java內(nèi)存區(qū)域理解-初步了解 http://iamzhongyong.iteye.com/blog/1333100
[2] Java HotSpot VM Options http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#Options

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內(nèi)容