天天看點

JVM

1、簡述java垃圾回收機制

java中不允許程式員自己操作記憶體管理,也不需要顯示的去釋放一個對象的記憶體,jvm虛拟機會自動執行管理這些記憶體。jvm虛拟機中有一個垃圾回收線程,它是低優先級的,在無特殊情況時不會觸發執行,當虛拟機空閑或者目前堆記憶體不足時才會執行觸發,它将自動掃描那些目前沒有被引用的對象将它們添加到回收集合中,進行回收。

2、gc是什麼?為什麼要gc

gc是垃圾回收集合的意思(gabage collection),在程式設計中例如c語言它是通過程式員處理記憶體的,然而記憶體處理往往容易出現各種問題忘記處理或者處理不當、操作錯誤記憶體等,這種回收會導緻程式或系統的不穩定甚至導緻崩潰,java為了避免這種情況的發生優化了這一環節,提供gc功能自動監測對象是否超過作用域進而實作自動回收記憶體,并且java不提供釋放已配置設定記憶體的顯示操作的方法,僅運作程式員提醒jvm此方法/變量可以被回收的方法(system.gc(),此函數建議jvm進行主gc,雖然隻是建議而非一定,但很多情況下它會觸發主gc,進而增加主gc的頻率,也即增加了間歇性停頓的次數。)

3、垃圾回收的優點和原理。并考慮2種回收機制

1、java最顯著的優點除了跨平台外還有一點就是垃圾回收機制,gc的存在使程式員不用去考慮記憶體管理的問題。2、這個垃圾回收機制讓java中的對象不再有“作用域”的概念,隻需要考慮引用對象的“作用域”。3、其還有效的防止了記憶體洩漏的問題,讓程式能夠有效的使用可用的記憶體。4、垃圾回收器通常作為一個單獨的低級别的線程運作,在不可預知的情況下對虛拟機記憶體堆中已經死亡或者長時間沒有被使用的對象進行清除和回收記憶體。5、程式員不能實時顯示的對某一個對象或者所有對象調用垃圾回收器進行垃圾回收。6、垃圾回收中将“垃圾”分級處理,分别是分代複制垃圾回收、标記垃圾回收、增量垃圾回收。

4、垃圾回收器的基本原理是什麼?垃圾回收器可以馬上回收記憶體嗎?有什麼辦法主動通知虛拟機進行垃圾回收?

通常來說當對象被建立時,gc就開始監控這個對象的位址、大小以及其使用情況。并且gc采用有向圖(一種圖表算法)的方式記錄和管理堆(heap)中的所有對象。通過這種方式确定那些對象是"可達的",那些對象是"不可達的"。當gc确定一些對象為"不可達"時,gc就有責任回收這些記憶體空間。

垃圾回收器是可以馬上回收記憶體的(這種需要看特殊情況)

程式設計人員可以手動的執行system.gc(),通知gc運作并回收垃圾,但是java中并不提倡這樣做也不保證gc就一定會執行。

5、java 中都有哪些引用類型?

強引用:發送gc的時候不會被回收

軟引用:有用但不是必須的對象,在發送記憶體溢出之前會被回收

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

虛引用:無法通過虛引用獲得對象,用phantomreference實作虛引用,虛引用的用途是在gc時傳回一個通知

6、怎麼判斷對象是否可以被回收?

垃圾收集器在做垃圾回收的時候,首先需要判定哪些對象是「存活」的,是不可以被回收的;哪些對象已經「死掉」了,需要被回收。兩種方法來判斷:

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

可達性分析算法:從 gc roots 開始向下搜尋,搜尋所走過的路徑稱為引用鍊。當一個對象到 gc roots 沒有任何引用鍊相連時,則證明此對象是可以被回收的。

7、在java中,對象什麼時候可以被垃圾回收

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

8、jvm中的永久代中會發生垃圾回收嗎?

垃圾回收不會發生在永久代,如果永久代滿了或者超過臨界值時,會觸發完全垃圾回收(full gc)。如果你仔細檢視垃圾收集器的輸出資訊,就會發現永久代也是會被回收的。這就是為什麼正确的永久大小對避免full gc 是非常重要的原因。(java8之前的jvm記憶體區包含新生代、老年代、永久代,但是在java8之後設計人員将永久代去除并新增加了一個中繼資料區的native記憶體區)

9、說一下 jvm 有哪些垃圾回收算法?

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

複制算法:按照容量劃分兩個大小相等的記憶體區域,當一塊用完的時候将活着的對象複制到另一塊區域上,然後再把已經使用的記憶體空間一次清空。缺點:記憶體使用率不高,隻使用了原來的一半。

标記-整理算法:标記無用的對象,讓所有存活的對象都向一端移動,然後直接清除掉端邊界以外的記憶體。

分代算法:根據對象的存活周期的不同将記憶體劃分為幾塊,分别是新生代和老年代,新生代基本采用複制算法,老年代采用标記整理算法。

10、說一下 jvm 有哪些垃圾回收器?

如果說垃圾手機算法是記憶體回收的方法論,那麼垃圾收集器就是記憶體回收的具體實作。

垃圾回收器按分代劃分,用于回收新生代的收集器包括 serial、pranew、parallelscavenge

用于回收老年代的收集器包括 serial old、parallel old、cms

用于回收整個java堆(heap)的 g1 收集器

以上的不同收集器之間實際工作中可以搭配使用

JVM

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堆(包括新生代,老年代),而前六種收集器回收的範圍僅限于新生代或老年代。

11、詳細介紹一下 cms 垃圾回收器?

cms 是英文 concurrent mark-sweep 的簡稱,是以犧牲吞吐量為代價來獲得最短回收停頓時間的垃圾回收器。對應的用于伺服器響應速度要求較高的應用上。這種垃圾回收器非常适合。在啟動 jvm 的參數加上“-xx:+useconcmarksweepgc”來指定使用 cms 垃圾回收器。

值得注意的是,cms 使用的是标記-清除的算法實作的,是以在 gc 的時候回産生大量的記憶體碎片,當剩餘記憶體不能滿足程式運作要求時,系統将會出現 concurrent mode failure,臨時 cms 會采用 serial old 回收器進行垃圾清除,此時的性能将會被降低。

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

新生代回收器:serial、parnew、parallel scavenge

老年代回收器:serial old、parallel old、cms

整堆回收器:g1

新生代垃圾回收器一般采用的是複制算法,複制算法的優點是效率高,缺點是記憶體使用率低;老年代回收器一般采用的是标記-整理的算法進行垃圾回收。

13、簡述分代垃圾回收器是怎麼工作的?

分代回收器有兩個分區:老生代和新生代,新生代預設的空間占比總空間的 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)時,更新為老生代。大對象也會直接進入老生代。

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

jvm