JVM知識
- 什么情況下會發(fā)生棧內(nèi)存溢出衷敌。
內(nèi)存溢出 out of memory勿侯,是指程序在申請內(nèi)存時,沒有足夠的內(nèi)存空間供其使用缴罗,出現(xiàn)out of memory助琐;比如申請了一個integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出面氓。
內(nèi)存泄露 memory leak兵钮,是指程序在申請內(nèi)存后,無法釋放已申請的內(nèi)存空間舌界,一次內(nèi)存泄露危害可以忽略掘譬,但內(nèi)存泄露堆積后果很嚴(yán)重,無論多少內(nèi)存,遲早會被占光禀横。
memory leak會最終會導(dǎo)致out of memory
內(nèi)存溢出就是你要求分配的內(nèi)存超出了系統(tǒng)能給你的屁药,系統(tǒng)不能滿足需求,于是產(chǎn)生溢出柏锄。
內(nèi)存泄漏是指你向系統(tǒng)申請分配內(nèi)存進(jìn)行使用(new)酿箭,可是使用完了以后卻不歸還(delete),結(jié)果你申請到的那塊內(nèi)存你自己也不能再訪問(也許你把它的地址給弄丟了)趾娃,而系統(tǒng)也不能再次將它分配給需要的程序缭嫡。一個盤子用盡各種方法只能裝4個果子,你裝了5個抬闷,結(jié)果掉倒地上不能吃了妇蛀。這就是溢出耕突!比方說棧,棧滿時再做進(jìn)棧必定產(chǎn)生空間溢出评架,叫上溢眷茁,棧空時再做退棧也產(chǎn)生空間溢出纵诞,稱為下溢上祈。就是分配的內(nèi)存不足以放下數(shù)據(jù)項(xiàng)序列,稱為內(nèi)存溢出.
解決:
1.少new 對象
2.調(diào)大xms,xmx參數(shù)
- JVM的內(nèi)存結(jié)構(gòu),Eden和Survivor比例浙芙。
HotSpot虛擬機(jī)GC算法采用分代收集算法:
1登刺、一個人(對象)出來(new 出來)后會在Eden Space(伊甸園)無憂無慮的生活,直到GC到來打破了他們平靜的生活嗡呼。GC會逐一問清楚每個對象的情況纸俭,有沒有錢(此對象的引用)啊,因?yàn)镚C想賺錢呀南窗,有錢的才可以敲詐嘛揍很。然后富人就會進(jìn)入Survivor Space(幸存者區(qū)),窮人的就直接kill掉矾瘾。
2女轿、并不是進(jìn)入Survivor Space(幸存者區(qū))后就保證人身是安全的箭启,但至少可以活段時間壕翩。GC會定期(可以自定義)會對這些人進(jìn)行敲詐,億萬富翁每次都給錢傅寡,GC很滿意放妈,就讓其進(jìn)入了Genured Gen(養(yǎng)老區(qū))。萬元戶經(jīng)不住幾次敲詐就沒錢了荐操,GC看沒有啥價值啦芜抒,就直接kill掉了。
3托启、進(jìn)入到養(yǎng)老區(qū)的人基本就可以保證人身安全啦宅倒,但是億萬富豪有的也會揮霍成窮光蛋,只要錢沒了屯耸,GC還是kill掉拐迁。
分區(qū)的目的:新生區(qū)由于對象產(chǎn)生的比較多并且大都是朝生夕滅的,所以直接采用標(biāo)記-清理算法疗绣。而養(yǎng)老區(qū)生命力很強(qiáng)线召,則采用復(fù)制算法,針對不同情況使用不同算法多矮。
JVM內(nèi)存為什么要分成新生代缓淹,老年代,持久代。新生代中為什么要分為Eden和Survivor讯壶。
JVM中一次完整的GC流程是怎樣的料仗,對象如何晉升到老年代,說說你知道的幾種主要的JVM參
數(shù)伏蚊。
- 你知道哪幾種垃圾收集器罢维,各自的優(yōu)缺點(diǎn),重點(diǎn)講下cms和G1丙挽,包括原理肺孵,流程,優(yōu)缺點(diǎn)颜阐。
CMS(并發(fā)GC)收集器
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標(biāo)的收集器平窘,適用于集中在互聯(lián)網(wǎng)站或者B/S系統(tǒng)的服務(wù)端的Java應(yīng)用。CMS收集器是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的凳怨,整個收集過程大致分為4個步驟:
①.初始標(biāo)記(CMS initial mark)
②.并發(fā)標(biāo)記(CMS concurrenr mark)
③.重新標(biāo)記(CMS remark)
④.并發(fā)清除(CMS concurrent sweep)
其中初始標(biāo)記瑰艘、重新標(biāo)記這兩個步驟任然需要停頓其他用戶線程。初始標(biāo)記僅僅只是標(biāo)記出GC ROOTS能直接關(guān)聯(lián)到的對象肤舞,速度很快紫新,并發(fā)標(biāo)記階段是進(jìn)行GC ROOTS 根搜索算法階段,會判定對象是否存活李剖。而重新標(biāo)記階段則是為了修正并發(fā)標(biāo)記期間芒率,因用戶程序繼續(xù)運(yùn)行而導(dǎo)致標(biāo)記產(chǎn)生變動的那一部分對象的標(biāo)記記錄,這個階段的停頓時間會被初始標(biāo)記階段稍長篙顺,但比并發(fā)標(biāo)記階段要短偶芍。
由于整個過程中耗時最長的并發(fā)標(biāo)記和并發(fā)清除過程中,收集器線程都可以與用戶線程一起工作德玫,所以整體來說匪蟀,CMS收集器的內(nèi)存回收過程是與用戶線程一起并發(fā)執(zhí)行的。
CMS收集器的優(yōu)點(diǎn):并發(fā)收集宰僧、低停頓材彪,但是CMS還遠(yuǎn)遠(yuǎn)達(dá)不到完美,主要有三個顯著缺點(diǎn):cpu敏感琴儿,浮動垃圾段化,空間碎片
CMS收集器對CPU資源非常敏感券躁。在并發(fā)階段隔躲,雖然不會導(dǎo)致用戶線程停頓,但是會占用CPU資源而導(dǎo)致引用程序變慢盗尸,總吞吐量下降谜疤。CMS默認(rèn)啟動的回收線程數(shù)是:(CPU數(shù)量+3) / 4佃延。
CMS收集器無法處理浮動垃圾现诀,可能出現(xiàn)“Concurrent Mode Failure“,失敗后而導(dǎo)致另一次Full GC的產(chǎn)生履肃。由于CMS并發(fā)清理階段用戶線程還在運(yùn)行仔沿,伴隨程序的運(yùn)行自熱會有新的垃圾不斷產(chǎn)生,這一部分垃圾出現(xiàn)在標(biāo)記過程之后尺棋,CMS無法在本次收集中處理它們封锉,只好留待下一次GC時將其清理掉。這一部分垃圾稱為“浮動垃圾”膘螟。也是由于在垃圾收集階段用戶線程還需要運(yùn)行成福,
即需要預(yù)留足夠的內(nèi)存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進(jìn)行收集荆残,需要預(yù)留一部分內(nèi)存空間提供并發(fā)收集時的程序運(yùn)作使用奴艾。在默認(rèn)設(shè)置下,CMS收集器在老年代使用了68%的空間時就會被激活内斯,也可以通過參數(shù)-XX:CMSInitiatingOccupancyFraction的值來提供觸發(fā)百分比蕴潦,以降低內(nèi)存回收次數(shù)提高性能。要是CMS運(yùn)行期間預(yù)留的內(nèi)存無法滿足程序其他線程需要俘闯,就會出現(xiàn)“Concurrent Mode Failure”失敗潭苞,這時候虛擬機(jī)將啟動后備預(yù)案:臨時啟用Serial Old收集器來重新進(jìn)行老年代的垃圾收集,這樣停頓時間就很長了真朗。所以說參數(shù)-XX:CMSInitiatingOccupancyFraction設(shè)置的過高將會很容易導(dǎo)致“Concurrent Mode Failure”失敗此疹,性能反而降低。
最后一個缺點(diǎn)蜜猾,CMS是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的收集器秀菱,使用“標(biāo)記-清除”算法收集后振诬,會產(chǎn)生大量碎片蹭睡。空間碎片太多時赶么,將會給對象分配帶來很多麻煩肩豁,比如說大對象,內(nèi)存空間找不到連續(xù)的空間來分配不得不提前觸發(fā)一次Full GC辫呻。為了解決這個問題清钥,CMS收集器提供了一個-XX:UseCMSCompactAtFullCollection開關(guān)參數(shù),用于在Full GC之后增加一個碎片整理過程放闺,還可通過-XX:CMSFullGCBeforeCompaction參數(shù)設(shè)置執(zhí)行多少次不壓縮的Full GC之后祟昭,跟著來一次碎片整理過程。
G1收集器
G1(Garbage First)收集器是JDK1.7提供的一個新收集器怖侦,是當(dāng)今收集器技術(shù)發(fā)展的最前沿成果之一篡悟。G1是一款面向服務(wù)端應(yīng)用的垃圾收集器谜叹。HotSpot開發(fā)團(tuán)隊(duì)賦予它的使命是(在比較長期的)未來可以替換掉JDK1.5中發(fā)布的CMS收集器。
與其他GC收集器相比搬葬,G1具備如下特點(diǎn):
1荷腊、并行與并發(fā):G1能充分利用多CPU、多核環(huán)境下的硬件優(yōu)勢急凰,使用多個CPU(CPU或CPU核心)來縮短Stop-The-World停頓的時間女仰,部分其他收集器原本需要停頓Java線程執(zhí)行的GC動作,G1收集器仍然可以通過并發(fā)的方式讓Java程序繼續(xù)執(zhí)行抡锈。
2疾忍、分代收集:與其他收集器一樣,分代概念在G1中依然得以保留床三。雖然G1可以不需要其他收集器配合就能單獨(dú)管理整個GC堆锭碳,但它能夠采用不同的方式去處理新創(chuàng)建的對象和已經(jīng)存活了一段時間、熬過多次GC的舊對象已獲得更好的收集效果勿璃。
3擒抛、空間整合:與CMS的“標(biāo)記-清除”算法不同,G1收集器從整體上看是基于“標(biāo)記-整理”算法實(shí)現(xiàn)的补疑,從局部(兩個Region之間)上看是基于“復(fù)制”算法實(shí)現(xiàn)的歧沪,但無論如何,這兩種算法都意味著G1運(yùn)行期間不會產(chǎn)生內(nèi)存空間碎片莲组,收集后能提供規(guī)整的可用內(nèi)存诊胞。這種特性有利于程序的長時間運(yùn)行,分配大對象時不會因?yàn)闊o法找到連續(xù)內(nèi)存空間而提前觸發(fā)下一次GC锹杈。
4撵孤、可預(yù)測的停頓:這是G1相對于CMS的另一大優(yōu)勢,降低停頓時間是G1和CMS共同的關(guān)注點(diǎn)竭望,但G1除了追求低停頓外邪码,還能建立可預(yù)測的停頓時間模型,能讓使用者明確指定在一個長度為M毫秒的時間片段內(nèi)咬清,消耗在垃圾收集上的時間不得超過N毫秒闭专,這幾乎已經(jīng)是實(shí)時Java(RTSJ)的垃圾收集器的特征了。
- 垃圾回收算法的實(shí)現(xiàn)原理旧烧。
look
1.引用計數(shù)法
2.標(biāo)記清除法
3.標(biāo)記壓縮
4.復(fù)制算法(高效影钉,新生代,老年代...)
當(dāng)出現(xiàn)了內(nèi)存溢出掘剪,你怎么排錯平委。
JVM內(nèi)存模型的相關(guān)知識了解多少,比如重排序夺谁,內(nèi)存屏障廉赔,happen-before愚墓,主內(nèi)存,工作
內(nèi)存等昂勉。
簡單說說你了解的類加載器浪册,可以打破雙親委派么,怎么打破岗照。
look講講JAVA的反射機(jī)制村象。
你們線上應(yīng)用的JVM參數(shù)有哪些。
lookg1和cms區(qū)別,吞吐量優(yōu)先和響應(yīng)優(yōu)先的垃圾收集器選擇攒至。
怎么打出線程棧信息厚者。
請解釋如下jvm參數(shù)的含義:
-server -Xms512m -Xmx512m -Xss1024K
-XX:PermSize=256m -XX:MaxPermSize=512m -
XX:MaxTenuringThreshold=20XX:CMSInitiatingOccupancyFraction=80 -
XX:+UseCMSInitiatingOccupancyOnly。
Xms20M -Xmx20M:最小堆內(nèi)存和最大堆內(nèi)存設(shè)置為一樣是為了避免堆內(nèi)存的自動擴(kuò)展
-Xmn10M:新生代內(nèi)存分配10M迫吐,剩余的交給老年代
-XX:SurvivorRatio=8:新生代中Eden區(qū)和Survivor區(qū)的內(nèi)存比例為8:1
-XX:PermSize=32M:永久代最小內(nèi)存32M
-XX:MaxPermSize=64M:永久代最大擴(kuò)展內(nèi)存64M
-XX:+HeapDumpOnOutOfMemoryError:堆內(nèi)存溢出時Dump出當(dāng)前的內(nèi)存堆轉(zhuǎn)儲快照以便事后分析