JVM必不可少的知識


1.Java垃圾回收機制

對象被判斷為垃圾的標准:沒有被其他對象引用

2.判斷對象是否可被回收

(1)引用計數算法

  判斷對象的引用數量

  • 通過判斷對象的引用數量來決定對象是否可以被回收
  • 每個對象實例都有一個引用計數器,被引用則+1,完成引用則-1
  • 任何引用計數為0的對象實例可以被當作垃圾回收

  優點:執行效率高,程序執行受影響較小

  缺點:無法檢測出循壞引用的情況,導致內存泄露

(2)可達性分析算法(引自離線數學的圖論)

通過判斷對象的引用鏈是否可達來決定對象是否可以被回收

可不可達判斷:如果從一個對象沒有到達根對象的路徑,或者說從根對象開始無法引用到該對象,該對象就是不可達的,具體看下圖。

0

什么可以作為GC Root的對象?

  • 虛擬機棧中引用的對象(棧幀中的本地變量表)
  • 方法區中的常量引用的對象
  • 方法區中的類靜態屬性引用的對象
  • 本地方法中JNI(Native方法)的引用對象
  • 活躍線程的引用對象

3.垃圾回收算法

(1)標記-清除算法

  • 標記:從根集合進行掃描,對存活的對象進行標記(可達性算法)
  • 清除:對堆內存從頭到尾進行線性遍歷,回收不可達對象內存

 缺點:碎片化

0

0

 

可以從上圖看出,空白的就是被回收的,會產生碎片

(2)復制算法

分為對象面和空閑面

原理:對象在對象面上創建,存活的對象被從對象面復制到空閑面,將對象面所有對象內存清除

解決碎片化問題

順序分配內存,簡單高效

適用於對象存活率低的場景

(3)標記-整理算法

  在標記清除算法的基礎上,解決了內存碎片化問題

  • 標記:從根集合進行掃描,對存活的對象進行標記(可達性算法)
  • 清除:移動所有存活的對象,且按照內存地址次序依次排列,然后將末端內存地址以后的內存全部回收

 好處:

  • 避免內存的不連續行
  • 不用設置兩塊內存互換
  • 適用於存活率高的場景

 

0

(4)分代收集算法

  • 垃圾回收算法的組合拳
  • 按照對象生命周期的不同划分區域以采用不同的垃圾回收算法

目的:提高jvm執行效率

jdk6,jdk7

0

jdk8及其以后的版本,永久代被去掉了

 0

  GC的分類

  • Minor GC(新生代GC)
  • Full GC(老年代GC)
0

1)年輕代

盡可能快速地收集掉那些生命周期短的對象

  • Eden區
  • 兩個Survivor區

年輕代垃圾回收的過程演示

0

存活對象被復制到S0,年齡+1,Eden區清空,如下圖

 0

如果Eden區又有對象,則把所有東西復制到S1,年齡+1,其他區東西清除,S1變為from區,S0變為to區

0
對象如何晉升到老年代
  • 經歷一定Minor次數依然存活的對象
  • Survivor區中存放不下的對象
  • 新生成的大對象(-XX:+PretenuerSizeThreshold)
常用的調優參數
  • -XX:SurvivorRatio:Eden和Survivor的比值,默認8:1
  • -XX:NewRatio:老年代和年輕代內存大小的比例
  • -XX:MaxTenuringThreshold:對象從年輕代晉升到老生代經過GC次數的最大閾值

2)老年代

存放生命周期較長的對象

常用的算法:

  • 標記-清理算法
  • 標記-整理算法
觸發Full GC的條件
  • 老年代空間不足
  • 永久代空間不足
  • CMS GC時出現promotion failed,concurrent mode failure
  • Minor GC晉升到老年代的平均大小大於老年代的剩余空間
  • 調用System.gc()
  • 使用RMI來進行RPC或管理的JDK應用,每小時執行1次Full GC

4.垃圾收集器

Stop-the-World

  • JVM由於要執行GC而停止了應用程序的執行
  • 任何一種GC算法中都會發生
  • 多數GC優化通過減少Stop-the-World發生的時間來提高程序性能

Safepoint(安全點)

  • 分析過程中對象引用關系不會發生變化的點
  • 產生Safepoint的地方:方法調用;循環判斷;異常跳轉等
  • 安全點數量得適中

jVM的運行模式

  • Server(啟動慢,但運行快,采用重量級虛擬機)
  • Client(啟動快,采用輕量級虛擬機)

垃圾收集器之間的聯系

 0

(1)年輕代常見垃圾收集器

1)Serial收集器(-XX:+UseSerialGC,復制算法)

JAVA虛擬機中最基本,歷史最悠久的收集器,在jdk1.3.1之前是年輕代收集器的唯一選擇。

  • 單線程收集,指的是進行垃圾收集時,必須暫停所有工作線程
  • 簡單高效,Client模式下默認的年輕代收集器

2)ParNew收集器(-XX:+UseParNewGC,復制算法)

  • 多線程收集,其余的行為、特點和Serial收集器一樣
  • 單核執行效率不如Serial,在多核下執行才有優勢

3)Parallel Scavenge收集器(-XX:+UseParallelGC,復制算法)

吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)

  • 比起關注用戶線程停頓時間,更關注系統的吞吐量(適用在后台運算,不需要太多交互的情況)
  • 在多核下執行才有優勢,Server模式下默認的年輕代收集器

(2)老年代常見垃圾收集器

1)Serial Old收集器(-XX:+UseSerialOldGC,標記-整理算法)

  • 單線程收集,指的是進行垃圾收集時,必須暫停所有工作線程
  • 簡單高效,Client模式下默認的年輕代收集器

2)Parallel Old收集器(-XX:+UseParallelOldGC,標記-整理算法)

  • 多線程,吞吐量優先

3)CMS收集器(-XX:+UseConcMarkSweepGC,標記-清除算法)

  • 初始標記:stop-the-world
  • 並發標記:並發追溯標記,程序不會停頓
  • 預清理:查找執行並發標記階段從年輕代晉升到老年代的對象
  • 重新標記:暫停虛擬機,掃描CMS堆中的剩余對象
  • 並發清理:清理垃圾對象,程序不會停頓
  • 並發重置:重置CMS收集器的數據結構

4)G1(Garbage First)收集器(-XX:+UseG1GC,復制+標記-整理算法)

  • 將整個Java堆內存划分成多個大小相等的Region
  • 年輕代和老年代不再物理隔離
特點
  • 並發和並行
  • 分代收集
  • 空間整合
  • 可預測的停頓

5.面試題

Object的finalize()方法的作用是否與C++的析構函數作用相同

  • 與C++的析構函數不同,析構函數調用確定,而它的是不確定的
  • 將未被引用的對象放置於F-Queue隊列(當垃圾回收器宣布一個對象死亡,至少需要經過兩個階段,1.當對象進行可達性分析時發現沒有和GC ROOTS相連接就會被第一次標記;2.判斷對象是否覆蓋finalize(),如果覆蓋,並且未被引用過這個方法的對象就會被放在F-Queue中,最后由JVM執行該方法)
  • 方法執行隨時可能會被終(優先級低)

強引用(Strong Reference)

  • 最普遍的引用:Object object = new Object()
  • 拋出OutOfMemoryError終止程序也不會回收具有強引用的對象
  • 通過將對象設置為null來弱化引用,使其被回收

軟引用(Soft Reference)

  • 對象出在有用但非必須的狀態
  • 只有當內存空間不足時,GC會回收該引用對象的內存
  • 可以用來實現高速緩存

弱引用(weak Reference)

  • 非必須的對象,比軟引用更弱一些
  • GC時會被回收
  • 被回收的概率也不大,因為GC線程優先級比較低
  • 適用於引用偶爾被使用且不影響垃圾收集的對象

虛引用(PhantomReference)

  • 不會決定對象的生命周期
  • 任何時候都可能被垃圾收集器回收
  • 跟蹤對象被垃圾收集器回收的活動,起哨兵作用
  • 必須和引用隊列ReferenceQueue聯合使用
String str = new Sring("abc"); // 強引用

SoftReference<String> sr = new SoftReference<String>(str); // 軟引用

WeakReference<String> sr = new WeakReference<String>(str); // 弱引用

ReferenceQueue queue = new ReferenceQueue();

PhantomReference ref = new PhantomReference(str,queue); // 虛引用

四種引用比較

引用級別:強引用>軟引用>弱引用>虛引用

 0

類層次結構

0

引用隊列(ReferenceQueue)

  • 無實際存儲結構,存儲邏輯依賴於內部節點之間的關系來表達
  • 存儲關聯的且被GC的軟引用,弱引用以及虛引用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM