在談垃圾收集器前先簡單的大致瞭解下垃圾收集算法
1. 標記清除算法
就是先標記需要回收的對象,然後統一回收所標記對象。
缺點:產生大量不連續的內存碎片,空間碎片太多可能會導致後期JVM需要分配大對象時,無法找到足夠連續內存空間,而再次觸發一次垃圾收集動作。
2. 複製算法
需要兩塊內存空間,只使用其中一塊。開始回收的時候將已使用的一塊內存空間中存活對象複製到另一塊內存空間,並一次性回收這塊內存空間。
缺點:會有一定的內存空間浪費
3. 標記-整理算法
有點像是整合了標記清除算法和複製算法。標記可回收對象,然後複製所有存活對象像一端移動。最後直接清理掉邊界外的內存。
4. 分代收集算法
內存區域根據對象存活週期劃分爲幾塊。新生代和老年代。新生代只有少量存活對象,使用複製算法。老年代因爲對象存活率較高,使用標記清理或者標記整理算法。
不同的垃圾收集器
1. Serial收集器
新生代收集器,歷史悠久的垃圾收集器,曾經是JDK1.3.1之前新生代收集的唯一選擇。
是一個單線程的收集器,需要暫停其他所有工作線程(用戶操作線程也需要一併停止),直到垃圾收集的結束。
client模式下默認
學習來源:《深入理解Java虛擬機》-- JDK1.7
2. ParNew收集器
新生代收集器,其實就是Serial收集器的多線程版本。在單CPU環境中不會比Serial收集器有更好的效果。
默認開啓線程數量與CPU數量相同,也可以使用-XX:ParalledGCThreads配置線程數量。
server模式下首選
學習來源:《深入理解Java虛擬機》-- JDK1.7
3. Parallel Scavenge收集器
新生代收集器,使用複製算法,多線程收集器(與Serial和ParNew一樣需要暫停所有其他線程),
可控吞吐量的垃圾收集器。
吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)。
1)-XX:MaxGCPauseMillis參與值是一個大於0的毫秒數。收集器儘可能的保證內存回收花費時間不超過設定值。
(JDK11默認值200)
2)-XX:GCTimeRatio參數值是一個大於0且小於100的整數。用來配置垃圾收集時間佔總時間的比率,相當於是吞吐量的倒數。(1/1+N)
例如:-XX:GCTimeRatio=19
1/(1+19)=0.05。即5%。
書中所寫默認值爲99
(JDK11默認值12)
3)-XX:UseAdaptiveSizePolicy開關參數。默認開啓。開關打開後就不需要手工指定新生代的大小(-Xmm)、Eden與Servivor區的比例(-XX:SurvivorRatio)、晉升老年代對象年齡(-XX:PretenureSizeThreshold)等細節參數。虛擬機會根據當前系統的運行情況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或者最大的吞吐量,這種調節方式成爲GC自適應的調劑策略。這也是Parallel Scavenge收集器與ParNew收集器的一個重要區別。
(JDK 1.8 默認使用 UseParallelGC 垃圾回收器,該垃圾回收器默認啓動了 AdaptiveSizePolicy)
無法與CMS配合使用。
學習來源:《深入理解Java虛擬機》-- JDK1.7
4. Serial Old收集器
Serial收集器的老年代版本。採用標記整理算法。
主要在client模式下使用。
如果在server模式下有兩大用途。一種是在JDK1.5以及之前的版本中與Parallel Scavenge收集器搭配使用。另一種用途就是作爲CMS收集器的後備預案,在併發收集發生Conncurrent Mode Failure時使用。
5. Paralled Old收集器
6. CMS收集器
7. G1收集器
111