堆是Java虛擬機進行垃圾回收的主要場所,其次要場所是方法區(qū)。
jvm堆內(nèi)存分為如下幾個部分:

和GC相關(guān)的JVM優(yōu)化:
1.創(chuàng)建的對象會優(yōu)先在Eden分配,如果是大對象(很長的字符串數(shù)組)則可以直接進入老年代。虛擬機提供一個-XX:PretenureSizeThreadhold參數(shù),令大于這個參數(shù)值的對象直接在老年代中分配,避免在Eden區(qū)和兩個Survivor區(qū)發(fā)生大量的內(nèi)存拷貝。
2.長期存活的對象將進入老年代,每一次MinorGC(年輕代GC),對象年齡就大一歲,默認15歲晉升到老年代,通過
-XX:MaxTenuringThreshold設(shè)置晉升年齡。
Minor GC(年輕代GC):對象優(yōu)先在Eden中分配,當Eden中沒有足夠空間時,虛擬機將發(fā)生一次Minor GC,因為Java大多數(shù)對象都是朝生夕滅,所以Minor GC非常頻繁,而且速度也很快。Full GC(老年代GC):Full GC是指發(fā)生在老年代的GC,當老年代沒有足夠的空間時即發(fā)生Full GC,發(fā)生Full GC一般都會有一次Minor GC。
為什么要有Survivor區(qū)?
為什么需要Survivor空間。我們看看如果沒有 Survivor 空間的話,垃圾收集將會怎樣進行:一遍新生代 gc 過后,不管三七二十一,活著的對象全部進入老年代,即便它在接下來的幾次 gc 過程中極有可能被回收掉。這樣的話老年代很快被填滿, Full GC 的頻率大大增加
JVM如何判定一個對象是否應(yīng)該被回收?
判斷一個對象是否應(yīng)該被回收,主要是看其是否還有引用。判斷對象是否存在引用關(guān)系的方法包括引用計數(shù)法以及可達性分析。
引用計數(shù)法:是一種比較古老的回收算法。原理是此對象有一個引用,即增加一個計數(shù),刪除一個引用則減少一個計數(shù)。垃圾回收時,只需要收集計數(shù)為0的對象。此算法最致命的是無法處理循環(huán)引用的問題。****可達性分析:可達性分析的基本思路就是通過一系列可以做為root的對象作為起始點,從這些節(jié)點開始向下搜索。當一個對象到root節(jié)點沒有任何引用鏈接時,則證明此對象是可以被回收的。以下對象會被認為是root對象:棧內(nèi)存中引用的對象方法區(qū)中靜態(tài)引用和常量引用指向的對象被啟動類(bootstrap加載器)加載的類和創(chuàng)建的對象Native方法中JNI引用的對象。
Java堆分為新生代和老年代,采用了不同的回收方式.
垃圾回收算法:
HotSpot 虛擬機采用了可達性分析來進行內(nèi)存回收,常見的回收算法有標記-清除算法,復(fù)制算法和標記整理算法。
標記-清除算法(Mark-Sweep):
標記-清除算法執(zhí)行分兩階段。
第一階段:從引用根節(jié)點開始標記所有被引用的對象,
第二階段:遍歷整個堆,把未標記的對象清除。此算法需要暫停整個應(yīng)用,并且會產(chǎn)生內(nèi)存碎片。
缺點:
執(zhí)行效率不穩(wěn)定,會因為對象數(shù)量增長,效率變低標記清除后會有大量的不連續(xù)的內(nèi)存碎片,空間碎片太多就會導(dǎo)致無法分配較大對象,無法找到足夠大的連續(xù)內(nèi)存,而發(fā)生gc
垃圾回收器:
JVM中的垃圾收集器主要包括7種,即Serial,Serial Old,ParNew,Parallel Scavenge,Parallel Old以及CMS,G1收集器。
CMS:
CMS收集器是一種以獲取最短回收停頓時間為目標的收集器。CMS收集器是基于標記-清除算法實現(xiàn)的,是一種老年代收集器,通常與ParNew一起使用。CMS的垃圾收集過程分為4步:初始標記:需要“Stop the World”,初始標記僅僅只是標記一下GC Root能直接關(guān)聯(lián)到的對象,速度很快。并發(fā)標記:是主要標記過程,這個標記過程是和用戶線程并發(fā)執(zhí)行的。重新標記:需要“Stop the World”,為了修正并發(fā)標記期間因用戶程序繼續(xù)運作而導(dǎo)致標記產(chǎn)生變動的那一部分對象的標記記錄(停頓時間比初始標記長,但比并發(fā)標記短得多)。并發(fā)清除:和用戶線程并發(fā)執(zhí)行的,基于標記結(jié)果來清理對象。
G1: