面試官:你對JVM垃圾收集器瞭解嗎?13連問你是否抗的住!

關於JVM垃圾收集器的面試題

一、簡述Java垃圾回收機制java

二、GC是什麼?爲何要GC程序員

三、垃圾回收的優勢和原理。並考慮2種回收機制面試

四、垃圾回收器的基本原理是什麼?垃圾回收器能夠立刻回收內存嗎?有什麼辦法主動通知虛擬機進行垃圾回收?算法

五、Java 中都有哪些引用類型?編程

六、怎麼判斷對象是否能夠被回收?服務器

七、在Java中,對象何時能夠被垃圾回收多線程

八、JVM中的永久代中會發生垃圾回收嗎併發

九、說一下 JVM 有哪些垃圾回收算法?ide

十、說一下 JVM 有哪些垃圾回收器?高併發

十一、詳細介紹一下 CMS 垃圾回收器?

十二、新生代垃圾回收器和老年代垃圾回收器都有哪些?有什麼區別?

1三、簡述分代垃圾回收器是怎麼工做的?

一、簡述Java垃圾回收機制

在java中,程序員是不須要顯示的去釋放一個對象的內存的,而是由虛擬機自行執行。在JVM中,有一個垃圾回收線程,它是低優先級的,在正常狀況下是不會執行的,只有在虛擬機空閒或者當前堆內存不足時,纔會觸發執行,掃面那些沒有被任何引用的對象,並將它們添加到要回收的集合中,進行回收。

二、GC是什麼?爲何要GC

GC 是垃圾收集的意思(Gabage Collection),內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存

回收會致使程序或系統的不穩定甚至崩潰,Java 提供的 GC 功能能夠自動監測對象是否超過做用域從而達到自動

回收內存的目的,Java 語言沒有提供釋放已分配內存的顯示操做方法。

三、垃圾回收的優勢和原理。並考慮2種回收機制

Java語言最顯著的特色就是引入了垃圾回收機制,它使java程序員在編寫程序時再也不考慮內存管理的問題。

因爲有這個垃圾回收機制,java中的對象再也不有「做用域」的概念,只有引用的對象纔有「做用域」。

垃圾回收機制有效的防止了內存泄露,能夠有效的使用可以使用的內存。

垃圾回收器一般做爲一個單獨的低級別的線程運行,在不可預知的狀況下對內存堆中已經死亡的或很長時間沒有用過的對象進行清除和回收。

程序員不能實時的對某個對象或全部對象調用垃圾回收器進行垃圾回收。

垃圾回收有分代複製垃圾回收、標記垃圾回收、增量垃圾回收。

四、垃圾回收器的基本原理是什麼?垃圾回收器能夠立刻回收內存嗎?有什麼辦法主動通知虛擬機進行垃圾回收?

對於GC來講,當程序員建立對象時,GC就開始監控這個對象的地址、大小以及使用狀況。

一般,GC採用有向圖的方式記錄和管理堆(heap)中的全部對象。經過這種方式肯定哪些對象是"可達的",哪些對象是"不可達的"。當GC肯定一些對象爲"不可達"時,GC就有責任回收這些內存空間。

能夠。程序員能夠手動執行System.gc(),通知GC運行,可是Java語言規範並不保證GC必定會執行。

五、Java 中都有哪些引用類型?

  • 強引用:發生 gc 的時候不會被回收。

  • 軟引用:有用但不是必須的對象,在發生內存溢出以前會被回收。

  • 弱引用:有用但不是必須的對象,在下一次GC時會被回收。

  • 虛引用(幽靈引用/幻影引用):沒法經過虛引用得到對象,用 PhantomReference 實現虛引用,虛引用的用途是在 gc 時返回一個通知。

六、怎麼判斷對象是否能夠被回收?

垃圾收集器在作垃圾回收的時候,首先須要斷定的就是哪些內存是須要被回收的,哪些對象是「存活」的,是不能夠被回收的;哪些對象已經「死掉」了,須要被回收。

通常有兩種方法來判斷:

  • 引用計數器法:爲每一個對象建立一個引用計數,有對象引用時計數器 +1,引用被釋放時計數 -1,當計數器爲 0 時就能夠被回收。它有一個缺點不能解決循環引用的問題;

  • 可達性分析算法:從 GC Roots 開始向下搜索,搜索所走過的路徑稱爲引用鏈。當一個對象到 GC Roots 沒有任何引用鏈相連時,則證實此對象是能夠被回收的。

七、在Java中,對象何時能夠被垃圾回收

當對象對當前使用這個對象的應用程序變得不可觸及的時候,這個對象就能夠被回收了。

垃圾回收不會發生在永久代,若是永久代滿了或者是超過了臨界值,會觸發徹底垃圾回收(Full GC)。若是你仔細查看垃圾收集器的輸出信息,就會發現永久代也是被回收的。這就是爲何正確的永久代大小對避免Full GC是很是重要的緣由。

八、JVM中的永久代中會發生垃圾回收嗎

垃圾回收不會發生在永久代,若是永久代滿了或者是超過了臨界值,會觸發徹底垃圾回收(Full GC)。若是你仔細查看垃圾收集器的輸出信息,就會發現永久代也是被回收的。這就是爲何正確的永久代大小對避免Full GC是很是重要的緣由。請參考下Java8:從永久代到元數據區

(譯者注:Java8中已經移除了永久代,新加了一個叫作元數據區的native內存區)

九、說一下 JVM 有哪些垃圾回收算法?

  • 標記-清除算法:標記無用對象,而後進行清除回收。缺點:效率不高,沒法清除垃圾碎片。

  • 複製算法:按照容量劃分二個大小相等的內存區域,當一塊用完的時候將活着的對象複製到另外一塊上,而後再把已使用的內存空間一次清理掉。缺點:內存使用率不高,只有原來的一半。

  • 標記-整理算法:標記無用對象,讓全部存活的對象都向一端移動,而後直接清除掉端邊界之外的內存。

  • 分代算法:根據對象存活週期的不一樣將內存劃分爲幾塊,通常是新生代和老年代,新生代基本採用複製算法,老年代採用標記整理算法。

標記-清除算法

標記無用對象,而後進行清除回收。

標記-清除算法(Mark-Sweep)是一種常見的基礎垃圾收集算法,它將垃圾收集分爲兩個階段:

  • 標記階段:標記出能夠回收的對象。

  • 清除階段:回收被標記的對象所佔用的空間。

標記-清除算法之因此是基礎的,是由於後面講到的垃圾收集算法都是在此算法的基礎上進行改進的。

優勢:實現簡單,不須要對象進行移動。

缺點:標記、清除過程效率低,產生大量不連續的內存碎片,提升了垃圾回收的頻率。

標記-清除算法的執行的過程以下圖所示

面試官:你對JVM垃圾收集器瞭解嗎?13連問你是否抗的住!

複製算法

爲了解決標記-清除算法的效率不高的問題,產生了複製算法。它把內存空間劃爲兩個相等的區域,每次只使用其中一個區域。垃圾收集時,遍歷當前使用的區域,把存活對象複製到另一個區域中,最後將當前使用的區域的可回收的對象進行回收。

優勢:按順序分配內存便可,實現簡單、運行高效,不用考慮內存碎片。

缺點:可用的內存大小縮小爲原來的一半,對象存活率高時會頻繁進行復制。

複製算法的執行過程以下圖所示

面試官:你對JVM垃圾收集器瞭解嗎?13連問你是否抗的住!

標記-整理算法

在新生代中可使用複製算法,可是在老年代就不能選擇複製算法了,由於老年代的對象存活率會較高,這樣會有較多的複製操做,致使效率變低。標記-清除算法能夠應用在老年代中,可是它效率不高,在內存回收後容易產生大量內存碎片。所以就出現了一種標記-整理算法(Mark-Compact)算法,與標記-整理算法不一樣的是,在標記可回收的對象後將全部存活的對象壓縮到內存的一端,使他們緊湊的排列在一塊兒,而後對端邊界之外的內存進行回收。回收後,已用和未用的內存都各自一邊。

優勢:解決了標記-清理算法存在的內存碎片問題。

缺點:仍須要進行局部對象移動,必定程度上下降了效率。

標記-整理算法的執行過程以下圖所示

面試官:你對JVM垃圾收集器瞭解嗎?13連問你是否抗的住!

分代收集算法

當前商業虛擬機都採用分代收集的垃圾收集算法。分代收集算法,顧名思義是根據對象的存活週期將內存劃分爲幾塊。通常包括年輕代、老年代 和 永久代,如圖所示:

面試官:你對JVM垃圾收集器瞭解嗎?13連問你是否抗的住!

十、說一下 JVM 有哪些垃圾回收器?

若是說垃圾收集算法是內存回收的方法論,那麼垃圾收集器就是內存回收的具體實現。下圖展現了7種做用於不一樣分代的收集器,其中用於回收新生代的收集器包括Serial、PraNew、Parallel Scavenge,回收老年代的收集器包括Serial Old、Parallel Old、CMS,還有用於回收整個Java堆的G1收集器。不一樣收集器之間的連線表示它們能夠搭配使用。

面試官:你對JVM垃圾收集器瞭解嗎?13連問你是否抗的住!

  • Serial收集器(複製算法): 新生代單線程收集器,標記和清理都是單線程,優勢是簡單高效;

  • ParNew收集器 (複製算法): 新生代收並行集器,其實是Serial收集器的多線程版本,在多核CPU環境下有着比Serial更好的表現;

  • Parallel Scavenge收集器 (複製算法): 新生代並行收集器,追求高吞吐量,高效利用 CPU。吞吐量 = 用戶線程時間/(用戶線程時間+GC線程時間),高吞吐量能夠高效率的利用CPU時間,儘快完成程序的運算任務,適合後臺應用等對交互相應要求不高的場景;

  • Serial Old收集器 (標記-整理算法): 老年代單線程收集器,Serial收集器的老年代版本;

  • Parallel Old收集器 (標記-整理算法): 老年代並行收集器,吞吐量優先,Parallel Scavenge收集器的老年代版本;

  • CMS(Concurrent Mark Sweep)收集器(標記-清除算法): 老年代並行收集器,以獲取最短回收停頓時間爲目標的收集器,具備高併發、低停頓的特色,追求最短GC回收停頓時間。

  • G1(Garbage First)收集器 (標記-整理算法): Java堆並行收集器,G1收集器是JDK1.7提供的一個新收集器,G1收集器基於「標記-整理」算法實現,也就是說不會產生內存碎片。此外,G1收集器不一樣於以前的收集器的一個重要特色是:G1回收的範圍是整個Java堆(包括新生代,老年代),而前六種收集器回收的範圍僅限於新生代或老年代。

十一、詳細介紹一下 CMS 垃圾回收器?

CMS 是英文 Concurrent Mark-Sweep 的簡稱,是以犧牲吞吐量爲代價來得到最短回收停頓時間的垃圾回收器。對於要求服務器響應速度的應用上,這種垃圾回收器很是適合。在啓動 JVM 的參數加上「-XX:+UseConcMarkSweepGC」來指定使用 CMS 垃圾回收器。

CMS 使用的是標記-清除的算法實現的,因此在 gc 的時候回產生大量的內存碎片,當剩餘內存不能知足程序運行要求時,系統將會出現 Concurrent Mode Failure,臨時 CMS 會採用 Serial Old 回收器進行垃圾清除,此時的性能將會被下降。

十二、新生代垃圾回收器和老年代垃圾回收器都有哪些?有什麼區別?

  • 新生代回收器:Serial、ParNew、Parallel Scavenge

  • 老年代回收器:Serial Old、Parallel Old、CMS

  • 整堆回收器:G1

新生代垃圾回收器通常採用的是複製算法,複製算法的優勢是效率高,缺點是內存利用率低;老年代回收器通常採用的是標記-整理的算法進行垃圾回收。

1三、簡述分代垃圾回收器是怎麼工做的?

分代回收器有兩個分區:老生代和新生代,新生代默認的空間佔比總空間的 1/3,老生代的默認佔比是 2/3。

新生代使用的是複製算法,新生代裏有 3 個分區:Eden、To Survivor、From Survivor,它們的默認佔比是 8:1:1,它的執行流程以下:

  • 把 Eden + From Survivor 存活的對象放入 To Survivor 區;

  • 清空 Eden 和 From Survivor 分區;

  • From Survivor 和 To Survivor 分區交換,From Survivor 變 To Survivor,To Survivor 變 From Survivor。

每次在 From Survivor 到 To Survivor 移動時都存活的對象,年齡就 +1,當年齡到達 15(默認配置是 15)時,升級爲老生代。大對象也會直接進入老生代。

老生代當空間佔用到達某個值以後就會觸發全局垃圾收回,通常使用標記整理的執行算法。以上這些循環往復就構成了整個分代垃圾回收的總體執行流程。

最後

歡迎關注公衆號:程序員追風,領取Java知識點學習思惟導圖總結+一線大廠Java面試題總結+一份300頁pdf文檔的Java核心知識點總結!

相關文章
相關標籤/搜索