點(diǎn)擊下方關(guān)注我,然后右上角點(diǎn)擊...“設(shè)為星標(biāo)”,就能第一時(shí)間收到更新推送啦~~~
8 個(gè)常見的 JVM 面試題分析。
1、什么時(shí)候會(huì)觸發(fā)垃圾回收,Minor GC 和 Full GC 的區(qū)別?
垃圾回收 GC 是由 JVM 根據(jù)運(yùn)行情況自動(dòng)完成的,觸發(fā)垃圾回收的時(shí)機(jī)是不確定的,當(dāng)然我們可以通過(guò)調(diào)用System.gc()方法通知 JVM 進(jìn)行垃圾回收,但是什么時(shí)候回收還是由 JVM 決定,但是不建議手動(dòng)調(diào)用System.gc()方法。一般以下幾種情況會(huì)發(fā)生垃圾回收
當(dāng)新生代(Eden 區(qū)或者 S 區(qū))空間不夠用時(shí),觸發(fā) Minor GC
當(dāng)老年代(Old 區(qū))空間不夠用時(shí),觸發(fā) Major GC,進(jìn)而可能觸發(fā) Full GC
當(dāng)方法區(qū)(Metaspace 區(qū))空間不夠用時(shí),觸發(fā) Full GC
Minor GC 指的是新生代的 GC,也就是 Young GC, Major GC 指的是老年代的 GC,也就是 Old GC,F(xiàn)ull GC 等于 Young GC+Old GC+Metaspace GC。
2、什么樣的對(duì)象是垃圾對(duì)象,垃圾對(duì)象一定會(huì)被回收嗎?
在可達(dá)性分析法中不可達(dá)的對(duì)象是垃圾對(duì)象,但是垃圾對(duì)象不一定就會(huì)被回收。
一個(gè)對(duì)象在可達(dá)性分析法中如果判定不可達(dá)會(huì)被初始標(biāo)記,初始標(biāo)記之后還需要進(jìn)行一次篩選分析(就是看該對(duì)象是否需要執(zhí)行 finalize() 方法)。
篩選分析過(guò)程:如果對(duì)象沒有覆蓋 finalize() ?方法或者 finalize() ?方法已經(jīng)被虛擬機(jī)調(diào)用過(guò),那么定該對(duì)象不需要執(zhí)行 finalize() ?方法;如果被判定為需要執(zhí)行 finalize() ?方法的對(duì)象,那么就會(huì)被放在一個(gè)隊(duì)列中進(jìn)行再次標(biāo)記。
再次標(biāo)記過(guò)程:再次標(biāo)記時(shí)如果這個(gè)對(duì)象在引用鏈上存在任何一個(gè)對(duì)象與之關(guān)聯(lián)那么就會(huì)被激活,否則就會(huì)被進(jìn)行垃圾回收。
3、為什么需要 Survivor 區(qū),只有 Eden 區(qū)可以嗎?為什么需要兩個(gè) Survivor 區(qū)?
如果沒有 Survivor 區(qū),Eden 區(qū)每進(jìn)行一次 Minor GC,并且沒有年齡限制的話,存活的對(duì)象就會(huì)被送到老年代。這樣一來(lái),老年代很快就會(huì)空間用完,觸發(fā) Major GC,老年代的內(nèi)存空間遠(yuǎn)大于新生代,進(jìn)行一次 Full GC消耗的時(shí)間比 Minor GC長(zhǎng)得多。
頻繁的 Full GC 消耗的時(shí)間很長(zhǎng),會(huì)影響應(yīng)用程序的執(zhí)行和響應(yīng)速度,一般會(huì)想到可以增加老年代空間降低 Full GC 頻率,或者減少老年代空間降低 Full GC所需時(shí)間。
如果對(duì)老年代的空間進(jìn)行增加,那么更多存活對(duì)象才能填滿老年代,這樣雖然降低了 Full GC 頻率,但是隨著老年代空間加大,一旦發(fā)生 Full GC,執(zhí)行垃圾清理所需要的時(shí)間更長(zhǎng)。如果減少老年代空間,雖然 Full GC 所需時(shí)間減少了,但是老年代很快被存活對(duì)象填滿,從而 Full GC 的頻率增加了。
所以 Survivor 區(qū)存在的意義就是發(fā)生 Minor GC 時(shí)把 Eden 區(qū)存活的對(duì)象放入 Survivor 區(qū),這樣可以減少被送到老年代的對(duì)象,進(jìn)而減少 Full GC 的發(fā)生,Survivor 區(qū)設(shè)置的年齡閾值默認(rèn) 15,也就是說(shuō)只有經(jīng)歷 16 次 Minor GC 還能在新生代中存活的對(duì)象,才會(huì)被送到老年代,從而大大減少了 ?Full GC 的觸發(fā)(垃圾回收要盡量減少垃圾回收的頻率)。
兩個(gè) Survivor 區(qū)最大的好處就是解決了 Young 區(qū)空間碎片化的問(wèn)題。假設(shè)現(xiàn)在只有一個(gè) Survivor 區(qū),新建的對(duì)象在 Eden 區(qū)中,一旦 Eden 區(qū)滿了,觸發(fā)一次 Minor GC,Eden 區(qū)中的存活對(duì)象就會(huì)被移動(dòng)到 Survivor 區(qū),這樣繼續(xù)循環(huán)下去,當(dāng)下一次 Eden 區(qū)滿了的時(shí)候,再次觸發(fā) Minor GC,這時(shí) Survivor 區(qū)可能有一些存活對(duì)象,導(dǎo)致 Survivor 區(qū)內(nèi)存是不連續(xù)的,也就導(dǎo)致了 Survivor 區(qū)內(nèi)存碎片化的問(wèn)題。再增加一個(gè) Survivor 區(qū),就能保證永遠(yuǎn)有一個(gè) Survivor 區(qū)是空的,另一個(gè)非空的 Survivor 區(qū)無(wú)碎片。
4、如果 Full GC 頻繁怎么辦?
Full GC 頻繁說(shuō)明老年代涌入了大量對(duì)象,這個(gè)時(shí)候就應(yīng)該檢查下 JVM 的參數(shù)配置,默認(rèn) Old:Young=2:1,很有可能是新生代設(shè)置的太小了,導(dǎo)致很多應(yīng)該在 Minor GC 階段就清理的對(duì)象留到了老年代,想辦法減少 Full GC 的次數(shù),可以適當(dāng)增加 Young 區(qū)的大小來(lái)解決。
新生代可以分為 Eden 區(qū)、S0 區(qū)、S1 區(qū),正常的對(duì)象分配都是在 Eden 區(qū)完成的,如果 Eden 區(qū)空間不夠了,會(huì)觸發(fā)一次 Minor GC,存活的對(duì)象放在 S0 或 S1 中。每執(zhí)行一次 Minor GC,存活的對(duì)象會(huì)不斷地從 S0 遷到 S1,再?gòu)?S1 遷到S0,這個(gè)過(guò)程經(jīng)過(guò)幾次之后,當(dāng)對(duì)象年齡為 15 時(shí),如果對(duì)象還是存活的就會(huì)把新生代的對(duì)象放入老年代中(年齡默認(rèn)是 15 歲,可以通過(guò)參數(shù) -XX:MaxTenuringThreshold
來(lái)設(shè)置)。如果新生代大小設(shè)置的太小,就會(huì)導(dǎo)致非常頻繁的 Minor GC, S0 和 S1 來(lái)回切換的速度加快,導(dǎo)致本身應(yīng)該在 Minor GC 就清理出去的對(duì)象跑到了老年代,從而導(dǎo)致 Full GC 的次數(shù)頻繁執(zhí)行。
5、只有 Full GC 才會(huì)觸發(fā) STW (stop the world)嗎?
STW (stop the world)指的是 GC 執(zhí)行過(guò)程中,可能會(huì)暫停應(yīng)用程序的執(zhí)行,這個(gè)停頓期間會(huì)導(dǎo)致所有應(yīng)用程序的線程都暫停執(zhí)行,沒有任何響應(yīng), 有點(diǎn)像卡死的感覺,這個(gè)停頓叫做 STW。
這種現(xiàn)象一般是由 GC 引起的,不管是什么 Full GC 還是 Young GC,都會(huì)有 STW,只是暫停時(shí)間的長(zhǎng)短不一樣,垃圾收集器的演進(jìn)過(guò)程就是為了更好地縮短這個(gè)停頓時(shí)間。
6、CMS 與 G1 垃圾收集器的區(qū)別?
CMS 和 G1 都是并發(fā)回收收集器,但是 CMS 只用于老年代的回收,而 G1 可用于新生代和老年代的回收。
CMS 使用標(biāo)記-清理算法實(shí)現(xiàn),G1 引入了 ?Region 內(nèi)存布局方式,使用標(biāo)記-整理算法實(shí)現(xiàn),整體減少了垃圾碎片的產(chǎn)生,CMS 和 G1 都在追求最短的用戶線程停頓時(shí)間為目標(biāo),但是 G1 比 CMS 先進(jìn)的是可以指定垃圾回收的停頓時(shí)間。
7、內(nèi)存泄漏和內(nèi)存溢出的區(qū)別?
內(nèi)存泄漏(memory leak):是指程序在申請(qǐng)內(nèi)存后,無(wú)法釋放已申請(qǐng)的內(nèi)存空間,導(dǎo)致對(duì)象無(wú)法得到及時(shí)的回收,持續(xù)占用內(nèi)存空間,從而造成內(nèi)存空間的浪費(fèi),內(nèi)存泄漏的堆積最終會(huì)導(dǎo)致內(nèi)存溢出。
內(nèi)存溢出(out of memory):內(nèi)存溢出就是我們常說(shuō)的 OOM,它是指程序在申請(qǐng)內(nèi)存時(shí),沒有足夠的內(nèi)存空間可以為其分配,就會(huì)內(nèi)存溢出;另外內(nèi)存溢出也有可能是大對(duì)象導(dǎo)致的。
8、方法區(qū)垃圾回收的內(nèi)容是什么?
方法區(qū)主要存儲(chǔ)的是類信息,那么方法區(qū)垃圾回收主要是回收“無(wú)用的類”和“無(wú)用的常量”。
如何判斷“無(wú)用的類” :
該類所有的實(shí)例都已經(jīng)被回收,也就是堆里面不再有該類任何實(shí)例對(duì)象
加載該類的 ClassLoader 已經(jīng)被回收
該類對(duì)應(yīng)的 java.lang.Class 對(duì)象沒有在任何地方被引用,也就是無(wú)法通過(guò)反射訪問(wèn)該類的方法
一個(gè)類需要同時(shí)滿足上面 3 個(gè)條件才能算是“無(wú)用的類” ,也就是說(shuō)虛擬機(jī)可以對(duì)其進(jìn)行垃圾回收。
運(yùn)行時(shí)常量池主要存儲(chǔ)的是常量信息,那么運(yùn)行時(shí)常量池回收主要是回收“無(wú)用的常量”。
如何判斷“無(wú)用的常量”:
假如在常量池中存在字符串常量"helloWorld" ,如果當(dāng)前沒有任何 String 對(duì)象引用該字符串常量的話,就說(shuō)明常量"helloWorld"就是“無(wú)用的常量”,也就是說(shuō)虛擬機(jī)可以對(duì)其進(jìn)行垃圾回收,"helloWorld"就會(huì)被虛擬機(jī)清理出常量池。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-642544.html
JVM?十三個(gè)應(yīng)知應(yīng)會(huì)知識(shí)點(diǎn)全部結(jié)束。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-642544.html
到了這里,關(guān)于常見的 JVM 面試題分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!