背景:用來總結java面試過程當中與jvm相關的問題。html
介紹經常使用的垃圾回收算法,垃圾收集器,垃圾收集器相關的調試參數。面試
jvm調優三大參數:數組
-Xss規定了每一個線程堆棧的大小。通常狀況下256K是足夠了。影響了此進程中併發線程數大小。併發
-Xms初始的Heap的大小。jvm
-Xmx最大Heap的大小。優化
在不少狀況下,-Xms和-Xmx設置成同樣的。這麼設置,是由於當Heap不夠用時,會發生內存抖動,影響程序運行穩定性。spa
JVM內存區域詳解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen).net
堆中:eden+survivor(from+to),old gen(老年代)
非堆:Code Cache、Perm Gen(永久代)、Jvm Stack(java虛擬機棧)、Local Method Statck(本地方法棧)
GC,即就是Java垃圾回收機制。目前主流的JVM(HotSpot)採用的是分代收集算法。與C++不一樣的是,Java採用的是相似於樹形結構的可達性分析法來判斷對象是否還存在引用。即:從gcroot開始,把全部能夠搜索獲得的對象標記爲存活對象。
GC機制
要準確理解Java的垃圾回收機制,就要從:「何時」,「對什麼東西」,「作了什麼」三個方面來具體分析。
第一:「何時」即就是GC觸發的條件。GC觸發的條件有兩種。(1)程序調用System.gc時能夠觸發;(2)系統自身來決定GC觸發的時機。
系統判斷GC觸發的依據:根據Eden區和From Space區的內存大小來決定。當內存大小不足時,則會啓動GC線程並中止應用線程。
第二:「對什麼東西」籠統的認爲是Java對象並無錯。可是準確來說,GC操做的對象分爲:經過可達性分析法沒法搜索到的對象和能夠搜索到的對象。對於搜索不到的方法進行標記。
第三:「作了什麼」最淺顯的理解爲釋放對象。可是從GC的底層機制能夠看出,對於能夠搜索到的對象進行復制操做,對於搜索不到的對象,調用finalize()方法進行釋放。
具體過程:當GC線程啓動時,會經過可達性分析法把Eden區和From Space區的存活對象複製到To Space區,而後把Eden Space和From Space區的對象釋放掉。當GC輪訓掃描To Space區必定次數後,把依然存活的對象複製到老年代,而後釋放To Space區的對象。
對於用可達性分析法搜索不到的對象,GC並不必定會回收該對象。要徹底回收一個對象,至少須要通過兩次標記的過程。
第一次標記:對於一個沒有其餘引用的對象,篩選該對象是否有必要執行finalize()方法,若是沒有執行必要,則意味可直接回收。(篩選依據:是否複寫或執行過finalize()方法;由於finalize方法只能被執行一次)。
第二次標記:若是被篩選斷定位有必要執行,則會放入FQueue隊列,並自動建立一個低優先級的finalize線程來執行釋放操做。若是在一個對象釋放前被其餘對象引用,則該對象會被移除FQueue隊列。
ps:
虛擬機的作法是進行兩次標記,即第一次標記不在「關係網」中的對象。第二次的話就要先判斷該對象有沒有實現finalize()方法了,若是沒有實現就直接判斷該對象可回收;若是實現了就會先放在一個隊列中,並由虛擬機創建的一個低優先級的線程去執行它,隨後就會進行第二次的小規模標記,在此次被標記的對象就會真正的被回收了。
GC過程當中用到的回收算法:
經過上面的GC過程不難看出,Java堆中的年輕代和老年代採用了不一樣的回收算法。年輕代採用了複製法;而老年代採用了標記-整理法
具體各類回收算法的詳解參考:http://www.cnblogs.com/dolphin0520/p/3783345.html
JVM內存空間圖解
程序計數器:線程私有。是一塊較小的內存,是當前線程所執行的字節碼的行號指示器。是Java虛擬機規範中惟一沒有規定OOM(OutOfMemoryError)的區域。
Java棧:線程私有。生命週期和線程相同。是Java方法執行的內存模型。執行每一個方法都會建立一個棧幀,用於存儲局部變量和操做數(對象引用)。局部變量所須要的內存空間大小在編譯期間完成分配。因此棧幀的大小不會改變。存在兩種異常狀況:若線程請求深度大於棧的深度,拋StackOverflowError。若棧在動態擴展時沒法請求足夠內存,拋OOM。
Java堆:全部線程共享。虛擬機啓動時建立。存放對象實力和數組。所佔內存最大。分爲新生代(Young區),老年代(Old區)。新生代分Eden區,Servior區。Servior區又分爲From space區和To Space區。Eden區和Servior區的內存比爲8:1。 當擴展內存大於可用內存,拋OOM。
方法區:全部線程共享。用於存儲已被虛擬機加載的類信息、常量、靜態變量等數據。又稱爲非堆(Non – Heap)。方法區又稱「永久代」。GC不多在這個區域進行,但不表明不會回收。這個區域回收目標主要是針對常量池的回收和對類型的卸載。當內存申請大於實際可用內存,拋OOM。
本地方法棧:線程私有。與Java棧相似,可是不是爲Java方法(字節碼)服務,而是爲本地非Java方法服務。也會拋StackOverflowError和OOM。
Minor GC ,Full GC 觸發條件
Minor GC觸發條件:當Eden區滿時,觸發Minor GC。
Full GC觸發條件:
(1)調用System.gc時,系統建議執行Full GC,可是沒必要然執行
(2)老年代空間不足
(3)方法去空間不足
(4)經過Minor GC後進入老年代的平均大小大於老年代的可用內存
(5)由Eden區、From Space區向To Space區複製時,對象大小大於To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小於該對象大小
jvm調優要重點掌握,面試必問,這篇文章講的很詳細,可是還要進行總結