在上一章中,咱們瞭解到程序計數器、虛擬機棧、本地方法棧等線程私有的區域的生命週期都是跟隨線程的生命週期的變化而變化的,而java堆和方法區等線程共享的區域的生命週期咱們就沒有介紹了。html
所以,本章的主要內容就是介紹java堆和方法區等線程共享的區域上管理,即java堆和方法區上GC。咱們將從如下幾個方面進行展開:java
要特別注意,本章節主要討論的是java堆和方法區上的GC。web
要想了解GC,首先要了解什麼是垃圾對象,或者說是什麼樣的對象才符合垃圾回收的原則?所謂的垃圾就是在jvm中用不到的內存區域,由於內存資源老是有限的,用不到的內存必定要從新被操做系統收集整理後再次使用。因此,垃圾回收的本質就是對內存空間的從新整理,把符合特定條件的內存區域從新回收,以供操做系統後期再次使用。算法
而線程私有的內存空間由線程本身管理,那線程共享的區域的管理就須要額外的功能模塊來管理了,這個額外的功能模塊就是垃圾回收器,又由於線程共享的區域上存儲的主要內容是java的類對象和方法。所以咱們就要研究什麼樣的對象纔可以被回收。瀏覽器
研究對象是否被回收,只須要研究對象是否被使用便可。換句話來講,就是研究對象是否被引用。目前來講,判斷對象是否被引用有兩種方式:安全
引用計數法:爲每個對象都建立一個引用計數的屬性,若是有其餘對象引用這個對象,就爲這個對象的引用計數的屬性加一,引用釋放時計數就減一,計數爲0的時候就能夠被回收了。這種方式沒法解決對象之間相互引用的問題。固然java中也不會使用這種方式來判斷對象是否存活了。服務器
可達性分析法:引入GCroot概念,若是在GCroot和一個對象之間沒有可達路徑,那麼對象就是不可達的。要注意的是:不可達對象不等價於可回收對象,不可達對象變成回收對象至少要通過兩次標記過程,兩次標記以後仍然是可回收對象,那將面臨回收。多線程
在Java語言中,GC Roots包括:併發
TODO: 可達性分析法的具體實現過程oracle
因爲java虛擬機規範中,沒有要求虛擬機在方法區實現垃圾收集,所以方法區的垃圾收集是根據具體的虛擬機實現來肯定的。在HotSpot中,方法區就是永久區。永久區的垃圾回收對象是廢棄常量和無用的類。
判斷一個類是否無用比較苛刻,要同時知足如下3個方面的條件:
垃圾回收由兩部分組成,一部分是GC算法,另外一部分是實現GC算法的回收器。
本小節主要研究垃圾回收算法的種類、具體實現原理、適用對象、優缺點等內容。
標記-整理算法
複製算法
標記-清除算法
分代回收算法
在早起的jdk版本中,咱們關注的是清理jvm中全部的垃圾,所以產生了單線程的Serial收集器和Serial Old收集器,這保證了清理時的穩定性與高效性,但這樣一樣會帶來一下問題,如因爲清理線程獨佔系統資源形成用戶程序線程暫停而引發全局停頓的問題;後來,咱們開始關注系統的吞吐量(即用戶應用程序運行時間與總運行時間的比值,吞吐量從某種意義上也體現了全局停頓時間的概念),咱們認爲要提升系統的吞吐量,所以產生了Parallel Scavenge收集器和Parallel Old收集器;再後來,咱們把關注點轉移到減小全局停頓時間上,所以產生了跨時代的CMS收集器。
此外,因爲在垃圾收集過程當中,會產生全局停頓的現象,這就引出咱們評判一個垃圾收集器性能好壞的評判標準:咱們在評判一個垃圾收集器性能好壞時,本質上講,咱們是在討論這個垃圾收集器在收集垃圾時所產生的全局停頓時間的長短,即全局停頓時間越短,垃圾收集器的性能越好
。可是這句話不是絕對的,咱們只是提供了一種觀察垃圾收集器性能好壞的方法。
下面的內容,咱們是從分代的角度去講述垃圾收集器的種類,固然讀者也能夠從垃圾收集器的發展階段中的關注點來劃分。本小節中也將主要講解各類回收器的種類、適用範圍、實現原理、優缺點、參數控制等內容。
上面的圖很是重要! 說明: 若是兩個收集器之間存在連線說明他們之間能夠搭配使用。
Serial收集器
-XX:+UseSerialGC
參數控制ParNew收集器
-XX:ParallelGCThreads
參數來限制垃圾收集器的線程數Parallel Scavenge收集器
-XX:MaxGCPauseMillis
參數來控制最大垃圾收集停頓時間-XX:GCTimeRatio
參數來直接設置吞吐量大小-XX:+UseAdaptiveSizePolicy
參數來開啓GC自適應的調節策略
,這個也是與Par New收集器的重要區別三個新生代收集器所採用的收集算法都是複製算法,而且它們的功能也是逐步完善的。ParNew收集器在Serial收集器的基礎上面加上了多線程的功能,Parallel Scavenge收集器又在ParNew收集器的基礎上加了控制吞吐量的控制功能。
Serial Old收集器
Parallel Old收集器
:star: CMS收集器
-XX:+CMSFullGCsBeforeCompaction
參數設置執行多少次不壓縮FullGC後,跟着來一次帶壓縮的。如:這個參數的值爲2,就是在執行2次不壓縮的FullGC以後,緊接着會再執行1次壓縮的FullGC)等G1收集器(又稱:Garbage—First)是目前技術發展的最前沿成果之一,它既能夠做用到新生代又能夠做用到老年代,所以它也被稱爲通用收集器。
相對於CMS垃圾收集器,它具備如下特色:
使用範圍
G1收集器的幾個重要內容
G1堆分配
-XX:G1HeapRegionSize
參數(該參數的默認值並非必定的,它是根據java堆初始化時大小決定的,取值範圍爲:1M到32M,且要是2的指數)來設置。新生代GC
老年代GC
GC的停頓主要來源於可達性分析上,程序執行時並不是在全部地方都能停頓下來開始GC,只有在到達安全點時才能暫停。
安全點的選定基本上是以程序「是否具備讓程序長時間執行的特徵」爲標準進行選定的——由於每條指令執行的時間都很是短暫,程序不太可能由於指令流長度太長這個緣由而過長時間運行,「長時間執行」的最明顯特徵就是指令序列複用,例如方法調用、循環跳轉、異常跳轉等,因此具備這些功能的指令纔會產生安全點。
接下來的問題就在於,如何讓程序在須要GC時都跑到安全點上停頓下來,大多數JVM的實現都是採用主動式中斷的思想。
主動式中斷的思想是當GC須要中斷線程的時候,不直接對線程操做,僅僅簡單地設置一個標誌,各個線程執行時主動去輪詢這個標誌,發現中斷標誌爲真時就本身中斷掛起,輪詢標誌的地方和安全點是重合的,另外再加上建立對象須要分配內存的地方。
// TODO
Serial收集器和SerialOld收集器
ParNew收集器與SerialOld收集器
Parallel Scavenge收集器和Parallel Old收集器
G1收集器
MinorGC日誌格式
FullGC日誌格式
調優工具分爲兩類,一類是jdk自帶的,一類是第三方的。
jps:JVM Process Status Tool,顯示指定系統內全部的HotSpot虛擬機進程。
jstat:JVM statistics Monitoring是用於監視虛擬機運行時狀態信息的命令,它能夠顯示出虛擬機進程中的類裝載、內存、垃圾收集、JIT編譯等運行數據。
jmap:JVM Memory Map命令用於生成heap dump文件
jhat:JVM Heap Analysis Tool命令是與jmap搭配使用,用來分析jmap生成的dump,jhat內置了一個微型的HTTP/HTML服務器,生成dump的分析結果後,能夠在瀏覽器中查看
jstack:用於生成java虛擬機當前時刻的線程快照。
jinfo:JVM Configuration info 這個命令做用是實時查看和調整虛擬機運行參數。
jconsole:Java Monitoring and Management Console是從java5開始,在JDK中自帶的java監控和管理控制檯,用於對JVM中內存,線程和類等的監控
jvisualvm:jdk自帶全能工具,能夠分析內存快照、線程快照;監控內存變化、GC變化等。
MAT,Memory Analyzer Tool,一個基於Eclipse的內存分析工具,是一個快速、功能豐富的Java heap分析工具,它能夠幫助咱們查找內存泄漏和減小內存消耗
GChisto:一款專業分析gc日誌的工具
// TODO
[0] : Jvm 系列(三):GC 算法 垃圾收集器
[1] : Java虛擬機(JVM)你只要看這一篇就夠了!
[2] : JVM看這一篇就夠了
[3] : JAVA核心知識點整理
[4] : 《深刻理解Java虛擬機——JVM高級特性與最佳實踐》
[5] : Java Hotspot G1 GC的一些關鍵技術
[6] : Getting Started with the G1 Garbage Collector
[7] :JVM GC參數以及GC算法的應用