JVM面試常問基礎(chǔ)總結(jié)

  • JVM內(nèi)存模型
  • JVM垃圾回收

1. JVM內(nèi)存模型

JVM內(nèi)存模型
  • 線程隔離的三個(gè)區(qū):
    • 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的行號(hào)指示器,指示運(yùn)行哪一行代碼;
    • JAVA虛擬機(jī)棧:存放局部變量等信息,服務(wù)于JAVA方法;
    • 本地方法棧:存放局部變量等信息,服務(wù)于本地方法;
  • 線程共享的兩個(gè)區(qū):
    • 方法區(qū):
      存放方法運(yùn)行時(shí)的常量、靜態(tài)變量等數(shù)據(jù);
      方法運(yùn)行結(jié)束后隨之釋放,可以無(wú)需垃圾回收;
    • JAVA堆:
      存放對(duì)象實(shí)例;
      垃圾回收管理的主要區(qū)域;

2. OOM

OutOfMemoryError 異常的簡(jiǎn)稱。

引起OOM的原因?

內(nèi)存溢出、內(nèi)存泄露。

內(nèi)存溢出:申請(qǐng)不到可用空間,需要進(jìn)行垃圾回收解決;
內(nèi)存泄露:無(wú)用的對(duì)象還繼續(xù)存活,且垃圾回收也無(wú)法將其回收。

OOM與SOF的區(qū)別?

  • 如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的最大深度,將拋出StackOverflowError;
  • 如果虛擬機(jī)在擴(kuò)展棧時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常。

3. GC(垃圾回收)

如何判斷對(duì)象是否存活?

  • 可達(dá)性分析算法:
    通過一系列的成為“GC Roots”的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開始向下搜索,搜索所走過的路徑成為引用鏈,當(dāng)一個(gè)對(duì)象到GC ROOTS沒有任何引用鏈相連時(shí),則證明此對(duì)象時(shí)不可用的。

可以作為GC Roots的對(duì)象:

  • 虛擬機(jī)棧中引用的對(duì)象
  • 本地方法棧引用的對(duì)象
  • 方法區(qū)中:
    • 靜態(tài)屬性引用的對(duì)象
    • 常量引用的對(duì)象

引用

  • 強(qiáng)引用:
    強(qiáng)引用有引用變量指向時(shí)永遠(yuǎn)不會(huì)被垃圾回收。
  • 軟引用:
    如果一個(gè)對(duì)象具有軟引用,內(nèi)存空間足夠,垃圾回收器就不會(huì)回收它;
    如果內(nèi)存空間不足了,就會(huì)回收這些對(duì)象的內(nèi)存。
  • 弱引用:
    當(dāng)JVM進(jìn)行垃圾回收時(shí),無(wú)論內(nèi)存是否充足,都會(huì)回收被弱引用關(guān)聯(lián)的對(duì)象。
  • 虛引用:
    擁有虛引用的對(duì)象可以在任何時(shí)候被垃圾回收器回收。

Finalize方法

任何一個(gè)對(duì)象的finalize()方法都只會(huì)被系統(tǒng)自動(dòng)調(diào)用一次,如果對(duì)象面臨下一次回收,它的finalize()方法不會(huì)被再次執(zhí)行。

4. 垃圾收集算法

標(biāo)記-清除算法、 標(biāo)記-整理算法、復(fù)制算法、分代收集算法

  • 標(biāo)記-清除算法:
    首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。
    問題:效率低、產(chǎn)生內(nèi)存碎片。
  • 標(biāo)記-整理算法:
    讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。
  • 復(fù)制算法:
    將可用內(nèi)存按照容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過的內(nèi)存空間一次清理掉。
    實(shí)際中我們并不需要按照1:1比例來(lái)劃分內(nèi)存空間,而是將內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor;
    當(dāng)另一個(gè)Survivor空間沒有足夠空間存放上一次新生代收集下來(lái)的存活對(duì)象時(shí),這些對(duì)象將直接通過分配擔(dān)保機(jī)制進(jìn)入老年代;
    不足:將內(nèi)存縮小為了原來(lái)的一半。
  • 分代收集算法
    把java堆分為新生代和老年代;
    對(duì)新生帶使用復(fù)制算法;
    對(duì)老年帶使用標(biāo)記清理或標(biāo)記整理方法。

5. 垃圾收集器

垃圾收集器關(guān)系的兩個(gè)問題:

  1. 停頓問題:進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程。
  2. 吞吐量:就是CPU用于運(yùn)行用戶代碼的時(shí)間與CPU總消耗時(shí)間的比值。
  • 三種新生代收集器
    • Serial:?jiǎn)尉€程、停頓;
    • ParNew:Serial的多線程版本;
    • Parallel Scavenge:使用復(fù)制算法,注重吞吐量。
  • 三種老年代收集器
    • Serial Old:Serial的老年帶版本;
    • Parallel Old:Parallel Sacvenge版本;多線程,標(biāo)記整理;
    • CMS:標(biāo)記清除;并發(fā)收集、低停頓;
  • 分代收集器:G1——新生代老年代都能收集
    最大特點(diǎn)與優(yōu)點(diǎn):可預(yù)測(cè)的停頓。

6. 內(nèi)存分配策略

  1. 對(duì)象優(yōu)先在新生代Eden分配;
  2. 大對(duì)象直接進(jìn)入老年代;
  3. 長(zhǎng)期存活的對(duì)象將進(jìn)入老年代;
  4. 動(dòng)態(tài)對(duì)象年齡判定;
  5. 空間分配擔(dān)保。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.一些概念 1.1.數(shù)據(jù)類型 Java虛擬機(jī)中,數(shù)據(jù)類型可以分為兩類:基本類型和引用類型?;绢愋偷淖兞勘4嬖?..
    落落落落大大方方閱讀 4,816評(píng)論 4 86
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,796評(píng)論 11 349
  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理,因此不免有一些不準(zhǔn)確的地方,同時(shí)不同JDK版本的...
    高廣超閱讀 16,051評(píng)論 3 83
  • 一. 垃圾回收的意義 在C++中,對(duì)象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對(duì)...
    Stan_Z閱讀 2,053評(píng)論 0 25
  • 人們都容易在工作時(shí)進(jìn)入忘我狀態(tài),這是很常見的現(xiàn)象。這些事情做起來(lái)相對(duì)而言是無(wú)意識(shí)的、自動(dòng)的大腦運(yùn)轉(zhuǎn)的結(jié)果。 如何高...
    靜寶sz閱讀 193評(píng)論 0 0

友情鏈接更多精彩內(nèi)容