GC這塊,當java才入門的時候,老師說java不像c++,c語言需要對內存進行管理,java有垃圾回收機制,會自動進行回收,是實際的生產中也沒關注過這些,現在回過頭好好了解下,發現裏面很有回收很多的機制。
####GC
GC(Garbage Collection)的基本原理:將內存中不再被使用的對象進行回收,GC中用於回收的方法稱爲收集器,由於GC需要消耗一些資源和時間,Java在對對象的生命週期特徵進行分析後,按照新生代、舊生代的方式來對對象進行收集,以儘可能的縮短GC對應用造成的暫停。
- 對新生代的對象的收集稱爲minor GC;
- 對舊生代的對象的收集稱爲Full GC;
- 程序中主動調用System.gc()強制執行的GC爲Full GC。
不同的對象引用類型, GC會採用不同的方法進行回收,JVM對象的引用分爲了四種類型:
- 強引用:默認情況下,對象採用的均爲強引用(這個對象的實例沒有其他對象引用,GC時纔會被回收)
- 軟引用:軟引用是Java中提供的一種比較適合於緩存場景的應用(只有在內存不夠用的情況下才會被GC)
- 弱引用:在GC時一定會被GC回收
- 虛引用:由於虛引用只是用來得知對象是否被GC
###垃圾收集算法
- 標記-清除算法
標記階段
標記存活對象
清除階段
統一回收所有未標記的對象
缺點
會產生內存碎片,如果空間內存碎片太多,當程序產生大對象無法在堆中找到連續空間大小存放的時候,會強制發生GC
- 複製算法
原理
內存一分爲二,每次只使用其中一塊,當一塊內存沒有連續空間存儲對象的時候,會把存活下來的對象複製到另外一塊內存中,然後一次性清除之前的哪塊空間
優缺點
- 沒有內存碎片問題
- 代價就是講內存減少了一半,空間利用率不高
- 不適用於存活對象較多的場景,比如老年代
- 而實際上我們並不需要按照1:1的比例來劃分,因爲大部分對象從創建到結束這個生命週期很短
- HotSpot虛擬機默認Eden:Survivor=8:1
- 標記-整理算法
原理
- 標記存活對象,然後把存活對象向一端移動
- 清理掉存活對象這端以外的所有空間
優缺點
- 適合用於存活對象較多的場合,如老年代
- 解決了空間碎片和效率問題:將所有的存活對象壓縮到內存的一端,然後清理邊界外所有的空間
- 分代收集算法
分代思想
- 堆劃分爲新生代和老年代
- 新生代中,能夠存活的對象很少,可以使用複製算法
- 老年代中,對象存活率高,而且沒有額外的空間用來做老年代的擔保,可以使用標記清除或者標記整理算法
###垃圾收集器-GC
- Serial 新生代串行收集器 新(複製算法),老(標記整理)
- ParNew 新生代並行收集器
- Parallel Scavenge 新生代並行收集器
- 目標:儘可能縮GC時用戶線程的停頓時間
- 在注重吞吐量或CPU資源敏感的場合,可以優先考慮Parallel
- Scavenge收集器 + Parallel Old收集器
- Serial Old 老年代串行收集器
- Parallel Old 老年代並行收集器
- CMS 真正意義上的併發收集器(老年代收集器)
- 目標:最短的GC停頓時間
- G1
Trace跟蹤參數
-verbose:gc
打印GC日誌信息
-XX:+PrintGCDetails
打印GC日誌信息
-Xloggc:d:/gc.log
GC日誌目錄
-XX:+PrintHeapAtGC
每次一次GC後,都打印堆信息
-XX:+TraceClassLoading
類加載信息
-XX:+PrintClassHistogram
配置了該參數後,在程序執行過程中,按下Ctrl+Break後,就可以打印類的信息
PS:其實說這麼多啊,最重要的還是使用打印的方式看看那個發生內存溢出的情況與數據操作有很大的關係,有助於優化程序。