帶着三個問題看垃圾回收
1.回收誰
2.何時回收
3.怎麼回收java
引用計數法:給對象中添加一個引用計數器,每當有對象引用它時,計數器就加1,引用失效就減1,計數器到0的時候表明不能使用該對象,不能解決循環引用的問題算法
可達性分析:經過GCRoots作爲起點,從這個起點向下搜索,當一個對象到GCRoots沒有任何引用鏈相連的時候,這個對象是不可用的,能夠回收。虛擬機棧(棧幀變量表中引用的對象),方法區(類的靜態屬性引用的對象,常量引用的對象),本地方法中JNI(Native引用的對象)
數組
"食之無味,棄之惋惜"
強引用(承認OOM,也不會回收)
軟引用(系統OOM以前,這些對象被回收)
弱引用(不管內存夠不夠,都會回收)
虛引用(只會收到回收通知)安全
"最後一刻掙扎"
一個對象的死亡,至少要被標記兩次,第一次看有沒有必要執行該對象中的finalize方法,若是該方法被調用過或者對象沒有覆蓋整個方法,就沒有必要執行finalize。若是執行了finalize,能夠在方法裏面自救,自救方案是與引用鏈上任何一個對象關聯便可。不建議使用服務器
方法區的回收
回收效率低,回收嚴謹。只有知足如下三點纔會回收
1.該類的全部實例都被回收,堆中不存在任何該類的實例
2.加載該類的ClassLoader已被回收
3.該類的java.lang.Class對象沒有任何地方被應用,沒法經過反射來訪問該類多線程
應用線程空閒時
內存滿的時候併發
標記清除算法
先標記要回收的對象,在統一清除。缺陷是會產生大量不連續的內存碎片,在分配大對象時,不得不提早觸發另外一次垃圾收集動做jvm
複製算法
將內存分AB兩塊,每次只用一塊,A的內存用完了,回收的時候就將A還存活的對象放在B上,而後統一清理A。缺陷是對象多的時候浪費複製時間,對內存的開銷也比較大。函數
標記整理算法
標記出全部要回收的對象,標記完成後,將存活的對象移動一端,而後清理掉端邊界之外的內存。工具
分代收集算法
根據新生代和老年代的特色,使用分代收集算法
由於新生代朝生夕死,因此用複製算法,僅須要複製少許對象。
老年代存活率高,對象多,沒有額外空間進行分配,就使用標記-整理算法。能夠自由搭配不少種,不過大體的類型就是如下幾種。
串行收集器(Serial)
-XX:+SerialGC
單線程收集器,這裏的單線程不是指垃圾回收的線程只有一個,而是相對於應用程序來說,在回收垃圾的時候要暫停應用程序(STW)
在內存不足時,串行GC設置停頓標識,當全部線程到達安全點後,應用程序暫停,開始垃圾收集。適合堆內存不高且單核的cpu使用。
並行收集器(ParNew,Parallel Scavenge)
-XX:+UseParNewGC
ParNew是Serial收集器的多線程版本,搭配老年代CMS首選。適合多核cpu。ParallelScavenge更關注吞吐量,一樣須要STW,適合和前臺交互少的系統,後臺處理任務量大的
併發收集器(CMS)
更關注低延遲的收集器,分爲如下四個階段,適合內存大,多核cpu。缺陷:消耗內存過的大,容易引發fullGC。有碎片,爲防止fullGC,默認開啓碎片整理參數
初始標記:以STW的方式標記全部根對象,很快
併發標記,與程序併發執行,標記出全部根路徑的可達路徑
從新標記,以STW標記有可能在這期間錯過的,一樣很快
併發清除,將不可達對象併發回收
G1收集器
引入了 Region概念,和CMS比較像,只不過有Region的優點
觀看GC日誌
33.125表明虛擬機啓動到如今,通過了多少秒
Full GC和GC表明停頓類型,不是爲了區分新生代和老年代的,若是有Full,表明是以SWT觸發的垃圾收集
DefNew,Tenured,Perm纔是區域,發生在什麼區域上的
3324K - > 152K(3712K) :GC前該內存區域已使用的容量 -> GC後該內存已使用的容量(總容量)
內存分配與回收策略
內存泄漏和內存溢出
內存泄漏是該釋放的對象沒有獲得釋放
內存溢出是撐爆了內存,對象太多了
JDK爲咱們提供的工具
列出當前機器上正在運行的虛擬機進程
-p :僅僅顯示VM 標示,不顯示jar,class, main參數等信息.
-m:輸出主函數傳入的參數. 下的hello 就是在執行程序時從命令行輸入的參數
-l: 輸出應用程序主類完整package名稱或jar完整名稱.
-v: 列出jvm參數, -Xms20m -Xmx50m是啓動程序指定的jvm參數
是用於監視虛擬機各類運行狀態信息的命令行工具。它能夠顯示本地或者遠程虛擬機進程中的類裝載、內存、垃圾收集、JIT編譯等運行數據,在沒有GUI圖形界面,只提供了純文本控制檯環境的服務器上,它將是運行期定位虛擬機性能問題的首選工具。
假設須要每250毫秒查詢一次進程2764垃圾收集情況,一共查詢20次,那命令應當是:jstat-gc 2764 250 20
經常使用參數:
-class (類加載器)
-compiler (JIT)
-gc (GC堆狀態)
-gccapacity (各區大小)
-gccause (最近一次GC統計和緣由)
-gcnew (新區統計)
-gcnewcapacity (新區大小)
-gcold (老區統計)
-gcoldcapacity (老區大小)
-gcpermcapacity (永久區大小)
-gcutil (GC統計彙總)
-printcompilation (HotSpot編譯統計)