1萝映、 簡(jiǎn)述JVM垃圾回收算法分類
常用的垃圾回收算法有如下四種:標(biāo)記-清除、復(fù)制罩阵、標(biāo)記-整理和分代收集竿秆。
標(biāo)記-清除算法
從算法的名稱上可以看出,這個(gè)算法分為兩部分稿壁,標(biāo)記和清除幽钢。首先標(biāo)記出所有需要被回收的對(duì)象,然后在標(biāo)記完成后統(tǒng)一回收掉所有被標(biāo)記的對(duì)象傅是。
這個(gè)算法簡(jiǎn)單匪燕,但是有兩個(gè)缺點(diǎn):一是標(biāo)記和清除的效率不是很高;二是標(biāo)記和清除后會(huì)產(chǎn)生很多的內(nèi)存碎片喧笔,導(dǎo)致可用的內(nèi)存空間不連續(xù)帽驯,當(dāng)分配大對(duì)象的時(shí)候,沒有足夠的空間時(shí)不得不提前觸發(fā)一次垃圾回收溃斋。
復(fù)制算法
這個(gè)算法將可用的內(nèi)存空間分為大小相等的兩塊界拦,每次只是用其中的一塊吸申,當(dāng)這一塊被用完的時(shí)候梗劫,就將還存活的對(duì)象復(fù)制到另一塊中,然后把原已使用過的那一塊內(nèi)存空間一次回收掉截碴。這個(gè)算法常用于新生代的垃圾回收梳侨。
復(fù)制算法解決了標(biāo)記-清除算法的效率問題,以空間換時(shí)間日丹,但是當(dāng)存活對(duì)象非常多的時(shí)候走哺,復(fù)制操作效率將會(huì)變低,而且每次只能使用一半的內(nèi)存空間哲虾,利用率不高丙躏。
標(biāo)記-整理算法
這個(gè)算法分為三部分:一是標(biāo)記出所有需要被回收的對(duì)象;二是把所有存活的對(duì)象都向一端移動(dòng)束凑;三是把所有存活對(duì)象邊界以外的內(nèi)存空間都回收掉晒旅。
標(biāo)記-整理算法解決了復(fù)制算法多復(fù)制效率低、空間利用率低的問題汪诉,同時(shí)也解決了內(nèi)存碎片的問題废恋。
分代收集算法
根據(jù)對(duì)象生存周期的不同將內(nèi)存空間劃分為不同的塊谈秫,然后對(duì)不同的塊使用不同的回收算法。一般把Java堆分為新生代和老年代鱼鼓,新生代中對(duì)象的存活周期短拟烫,只有少量存活的對(duì)象,所以可以使用復(fù)制算法迄本,而老年代中對(duì)象存活時(shí)間長(zhǎng)硕淑,而且對(duì)象比較多,所以可以采用標(biāo)記-清除和標(biāo)記-整理算法岸梨。
2喜颁、 敘述JVM常用的調(diào)優(yōu)參數(shù)
-Xmx :堆的最大值?
-Xms :堆的最小值,即初始值? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?##可以讓xms=xmx
-XX:NewSize=1024MB :新生代初始大小
-XX:MaxNewSize=1024MB :新生代最大值
-XX:NewRatio=m :New和Old的比值
-Xmn=1024MB :新生代大小? ? ? ? ? ? ? ? ? ? ? ? ? ##一般使用-Xmn來(lái)固定新生代大小
-XX:SurvivorRatio=m :Eden和Survivor的比值
-XX:TargetSurvivorRatio=n :minor GC后Survivor預(yù)期被占用的比例
-XX:+UseConcMarkSweepGC :新生代使用ParNew曹阔,老生代優(yōu)先使用CMS半开,備用方式為Serial Old
-XX:+CMSFullGCsBeforeCompaction : 在多少次回收后執(zhí)行一次內(nèi)存碎片整理
-XX:+PrintTenuringDistribution :查看每次minor GC后年齡的分布和計(jì)算出來(lái)的TenuringThreshold
-XX:+PrintGC :輸出GC簡(jiǎn)要信息
-XX:+PrintGCDetails :輸出GC信息
-XX:+PrintGCTimeStamps :輸出GC時(shí)間戳
-XX:+PrintGCApplicationStoppedTime :輸出GC暫停時(shí)間
-Xlogg c:/gc.log? ? ? ? 輸出到文件
3、 JAVA進(jìn)程發(fā)生OOM如何調(diào)優(yōu)
最常見的OOM情況有以下三種:
?? ? java.lang.OutOfMemoryError: Java heap space ------>java堆內(nèi)存溢出赃份,此種情況最常見寂拆,一般由于內(nèi)存泄露或者堆的大小設(shè)置不當(dāng)引起。對(duì)于內(nèi)存泄露抓韩,需要通過內(nèi)存監(jiān)控軟件查找程序中的泄露代碼纠永,而堆大小可以通過虛擬機(jī)參數(shù)-Xms,-Xmx等修改。
?? ? java.lang.OutOfMemoryError: PermGen space ------>java永久代溢出谒拴,即方法區(qū)溢出了尝江,一般出現(xiàn)于大量Class或者jsp頁(yè)面,或者采用cglib等反射機(jī)制的情況英上,因?yàn)樯鲜銮闆r會(huì)產(chǎn)生大量的Class信息存儲(chǔ)于方法區(qū)炭序。此種情況可以通過更改方法區(qū)的大小來(lái)解決,使用類似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改苍日。另外惭聂,過多的常量尤其是字符串也會(huì)導(dǎo)致方法區(qū)溢出。
?? ? java.lang.StackOverflowError ------> 不會(huì)拋OOM error相恃,但也是比較常見的Java內(nèi)存溢出辜纲。JAVA虛擬機(jī)棧溢出,一般是由于程序中存在死循環(huán)或者深度遞歸調(diào)用造成的拦耐,棧大小設(shè)置太小也會(huì)出現(xiàn)此種溢出耕腾。可以通過虛擬機(jī)參數(shù)-Xss來(lái)設(shè)置棧的大小杀糯。
OOM分析--heapdump
要dump堆的內(nèi)存鏡像扫俺,可以采用如下兩種方式:
?? ? 設(shè)置JVM參數(shù)-XX:+HeapDumpOnOutOfMemoryError,設(shè)定當(dāng)發(fā)生OOM時(shí)自動(dòng)dump出堆信息火脉。不過該方法需要JDK5以上版本牵舵。
?? ? 使用JDK自帶的jmap命令柒啤。"jmap -dump:format=b,file=heap.bin <pid>"? 其中pid可以通過jps獲取。
dump堆內(nèi)存信息后畸颅,需要對(duì)dump出的文件進(jìn)行分析担巩,從而找到OOM的原因。常用的工具有:
?? ? mat: eclipse memory analyzer, 基于eclipse RCP的內(nèi)存分析工具没炒。
?? ? jhat:JDK自帶的java heap analyze tool涛癌,可以將堆中的對(duì)象以html的形式顯示出來(lái),包括對(duì)象的數(shù)量送火,大小等等拳话。