日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java内存组成GC算法

發布時間:2024/1/23 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java内存组成GC算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java內存組成&GC算法

@(JAVA)[java]

  • Java內存組成GC算法
  • 一內存組成
    • 一Java程序的內存組成
      • 1Java堆
      • 2方法區含常量池永久代
      • 3棧
        • 1Java虛擬機棧
        • 2本地方法棧
      • 4程序計數器
      • 5直接內存
    • 二各種OOM情形模擬
      • 1Java堆溢出
      • 2方法區含常量池溢出
      • 3棧溢出
      • 4直接內存溢出
      • 5其它
  • 二GC算法
    • 一算法基礎
      • 1標記判斷對象是否生存的算法
        • 1引用次數算法
        • 2可達路徑算法
      • 2清除垃圾回收算法
        • 1標記-清除算法
        • 2標記-復制算法
        • 3標記-整理算法
    • 二常用算法
      • 1Serial串行收集器
      • 2ParNew并行收集器
      • 3Parallel Scanvenge簡稱Parallel也稱Throughput吞吐量優先收集器
      • 4ConcurrentMarkSweep
      • 5G1
    • 三GC組合
      • 1-XXUseSerialGC
      • 2-XXUseParNewGC
      • 3-XXUseParallelGC
      • 4-XXUseParllelOldGC
      • 5-XXUseConcMarkSweepGC
      • 6-XXUseG1GC
    • 四ParNew
      • 1重要選項
      • 2日志說明
    • 五CMS
      • 1優缺點
      • 2CMS的基本流程
      • 3CMS完整流程日志
      • 4CMS的重要配置參數
      • 6CMS一個常見的錯誤concurrent mode failure
    • 六G1
  • 三JVM重要參數
      • 1-Xmngmk
      • 2-Xms -Xmx
      • 3-XXPermSizegmk -XXMaxPermSizegmk
      • 4-Xss
      • 5 -XXNewRatio -XXSurvivorRatio
      • 6client與server模式
      • 7-32與-64
      • 8GC日志打印相關
  • 四常用工具及命令
    • 一最常用命令
    • 二常用命令
      • 1jps
      • 2jstat
        • 1 jstat -gcutil 10763 1000 100
        • 2jstat -gc 27787 1000 10
      • 3jinfo
      • 4jmap 與 jhat結合使用java內存映像工具與分析工具
        • 簡單步驟
        • 什么是 Java heap dump
        • 觸發 Java heap dump的方法
        • 分析 Java heap dump
      • 5jmap的其它用法
        • 1jmap -heap 15914
        • 2jmap -histo 15914
      • 6jstack
    • 三使用visualvm遠程監控java進程以hadoop進程為例
    • 四使用gcviewer分析GC日志

一、內存組成

(一)Java程序的內存組成

* 簡單概述:堆用于存放對象實例;方法區(永久代)用于存放常量、類及方法的字節碼、方法傳遞參數等;棧用于存放操作數棧、基本類型數據等。*

1、Java堆

這是Java程序使用最大內存的部分。Java堆是被所有線程共享的內存區域,在虛擬機啟動時創建。此內存用于存放對象實例。
Java堆是GC的主要區域,因此也會被稱為GC堆。
Java堆被分為新生代和老生代2部分。

2、方法區(含常量池、永久代)

與Java堆類似,這是所有線程共享的內存區域。它包括常量池、域、方法數據、方法和構造方法的字節碼、類、實例、接口初始化時用到的特殊方法。
雖然Java虛擬機規范把方法區描述為堆的一個邏輯部分,但它卻有一個別名叫Non-Heap。
很多人把方法區稱為永久代,本質上二者并不等價,只是HotSpot把GC分代收集擴展至方法區,或者說使用永久代來實現方法區而已。在hotspot中,永久代被放在堆中,并隨full GC時被回收,主要回收常量及類的卸載。
對于HotSpot,已經有規劃放棄永久代并逐步使用Native Memory來實現方法區了。目前已經把運行時常量池遷出。

3、棧

(1)Java虛擬機棧

Java虛擬機棧是線程私有的。每個方法在執行的同時都會創建一個Stack Frame,用于存儲局部變量表、操作數棧、動態鏈接、方法出入口等信息。

關于堆和棧的說明:堆用于儲存各種對象,而棧的局部變量表是保存基本類型的數據以及對象的指針(非對象自身)

(2)本地方法棧

與上面說的Java虛擬機棧作用非常類似,只是Java虛擬機棧為虛擬機執行Java方法服務,而本地方法棧則為虛擬機使用到的Native方法服務。

4、程序計數器

程序計數器是線程私有的。
如果線程正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果正在執行的是Native方法,這個計數器的值為空。
此區域是唯一一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域。

5、直接內存

直接內存并不是虛擬機運行時數據區的一部分。
在NIO中,引入了基于通道與緩沖區的IO方式,它可以使用Native函數庫直接分配堆外內存,然后通過一個存儲在Java堆中的DirectByteBuffer對象作為這塊內存的引用進行操作。這樣能在一些場景中顯著提高性能,因為避免了在Java堆和Native堆中來回復制數據。

Direct Memory不能像新生代、老生代那樣,發現內存不足了就通知JVM進行GC,它是等老生代滿了,進行full GC時順便進行回收的,因此過度使用Direct Memory有可能導致OOM
或者可以通過–XX:MaxDirctMemorySize來調整大小

(二)各種OOM情形模擬

1、Java堆溢出

我們創建一個List,然后寫入大量的對象直接內存溢出:

public class JavaHeapOOMDemo {public static void main(String[] args) {List<Integer> list = new LinkedList<Integer>();Random random = new Random();while(true){list.add(new Integer(random.nextInt()));}} }

運行時加上以下JVM參數:

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

指定了最大的堆內存,并在OOM發生時dump出內存中的內容。運行后console顯示:

java.lang.OutOfMemoryError: GC overhead limit exceeded Dumping heap to java_pid7268.hprof ... Heap dump file created [37801092 bytes in 0.652 secs] Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceededat com.lujinhong.commons.java.oom.JavaHeapOOMDemo.main(JavaHeapOOMDemo.java:25)

注意第一行GC overhead limit exceeded,每種OOM都有其相應的內容。
使用IBM HeapAnalyzer分析dump出來的結果

發現有一個List對象占用了98.5%的內存,它包含了498788個Integer對象。

發生堆OOM有2種可能:
* 一是內存真的不夠分配所需的對象了,這只能高大堆,或者是優化代碼。
* 二是內存泄漏了,某些對象無法被GC回收。

2、方法區(含常量池溢出)

錯誤現象是

Caused by: java.lang.OutOfMemoryError: PermGen space

即永久出錯,但JDK7有了變化。

3、棧溢出

一個常見的情況是遞歸調用時沒有終結條件。

public class JavaVMStackSOF {public static int add(int a, int b){return add( a, b);}public static void main(String[] args) {add(1,1);}}

運行時出現以下錯誤:

Exception in thread "main" java.lang.StackOverflowErrorat com.lujinhong.commons.java.oom.JavaVMStackSOF.add(JavaVMStackSOF.java:13)at com.lujinhong.commons.java.oom.JavaVMStackSOF.add(JavaVMStackSOF.java:13)at com.lujinhong.commons.java.oom.JavaVMStackSOF.add(JavaVMStackSOF.java:13)at com.lujinhong.commons.java.oom.JavaVMStackSOF.add(JavaVMStackSOF.java:13)at com.lujinhong.commons.java.oom.JavaVMStackSOF.add(JavaVMStackSOF.java:13)

這是超出了棧允許的最大深度,并不是OOM。

  • 如果線程請求的棧深度大于虛擬機所允許的最大深度,將拋出StackOverflowError。
  • 如果虛擬機在擴展棧時無法申請到足夠的內存空間,則拋出OOM,此時會報OutOfMemoryError: Unable to create new native thread.
    可以通過-Xss來指定這部分內存的大小。

4、直接內存溢出

直接內存容量可以通過-XX:MaxDirectMemorySize指定,如果不指定,則與-Xmx一樣。

如果發現OOM之后Dump文件很小,而程序又直接或者間接的使用了NIO,則可以考慮一下是否直接內存溢出了。直接內存溢出時會出現OutOfMemoryError:Direct Buffer memory.這種錯誤。

5、其它

還有一些其它情況,并不是OOM,但也是資源使用過量,如:
(1)Socket緩沖區

連接過多的話有可能出現IOExecption: Too many open file。此時一般是有一些資源未關閉導致的,如socket, 文件等。一個例子是kafka的producer未使用close(), 而又在不斷的新建連接。

二、GC算法

(一)算法基礎

當前主流的JVM均使用mark-sweep的算法進行垃圾回收。因此,關于垃圾回收有2個關鍵的步驟:
* 標記哪些對象已經死亡,即可以回收的。
* 回收被標記的對象。
這部分描述的只是算法的原理,具體實現細節根據JVM的不同而不同。

1、標記:判斷對象是否生存的算法

(1)引用次數算法

記錄每個對象被多少個其它對象引用,當引用次數變為0時,則這個對象被標記為可回收。這個方法實現簡單,高效,但它不能解決對象的循環引用問題:

A.instance = B; B.instance = A;

上述代碼中,A與B是同一個類的對象,它們互相引用。但除了這部分代碼以外,它們沒有在其余任何地方被引用,因為對應引用來說,它們應該是沒用的對象,可以進行回收的。但引用次數算法并不能解決這問題。

(2)可達路徑算法

從幾個GC root出發,遍歷所有對象,當某些對象不能從GC root到達,則認為這個對象已經死掉,可回收。

GC root一般是一些合局的靜態成員、表態常量等。

* 關于引用的說明:引用按強弱程度可分為強引用、軟引用、弱引用、虛引用。強引用不能被回收,后面3個根據內存的情況以及被標記的次數來決定是否回收。如緩存之類的對象可回收也可不回收的。*

2、清除:垃圾回收算法

當對象被標記為可回收后,下一步就是回收這些對象了(當然會有觸發條件,比如內存滿了、System.gc()等),下面看一下如何回收。

(1)標記-清除算法

這是最簡單的實現方法,就是將內存中標記為可清除的對象刪除。這種方法實現簡單且高效,但會形成大量的內存碎片,有可能導致大對象無法寫入。

(2)標記-復制算法

將內存分成2個部分,每次只使用一個部分。當有垃圾回收需求時,將還生存的對象一次性的全部復制到另一部分內存,原來那部分內存即可直接清空。
這有一個明顯的問題是,內存占用多了一倍。

IBM研究發現,新生代的對象符合“朝生夕滅”的特征,即98%以上的對象在第一次GC時就會被回收。因此現在的新生代一般分成3部分: eden, survivor1, survivor2,它們之間的默認比例為8:1:1。
新生代只使用eden及其中一個survivor區,新對象均會在eden區進行分配,當需要GC時,將eden及survivor中還存活的對象一次復制到另一個survivor中。這種方法只浪費了其中10%的內存。

* 此算法是目前主要JVM新生代的主流回收算法 *

(3)標記-整理算法

上述標記-整理算法并不適用于老生代,因為老生代的對象并不符合“朝生夕滅”的特征,而是有很多對象一直存活到程序結束的。而同時為了避免標記-清除算法留下的內存碎片,不再直接清除對象,而是將對象移到內存堆中的前面,整整齊齊的排列。

(二)常用算法

在JDK歷史中出現過很多種GC算法,這里只列舉出在hostpot中曾經或者現在被廣泛使用的算法實現。

1、Serial:串行收集器

(1)應用線程停止工作,Stop-the-word。
(2)單線程進行垃圾回收。
主要包括2種具體的實現:
* Serial收集器:作用于新生代,基于標記-復制算法。
* Serial Old收集器:作用于老生代,基于標記-整理算法。

2、ParNew:并行收集器

(1)應用線程停止工作,Stop-the-word。
(2)多線程進行垃圾回收。
主要包括2咱具體實現:
* ParNew收集器:作用于新生代,基于標記-復制算法。
* Parllel Old收集器:作用于老生代,基于標記-整理算法。

3、Parallel Scanvenge(簡稱Parallel,也稱Throughput)吞吐量優先收集器

(1)可以設置期望GC時間上限,以及GC時間占總時間的比例,以用來控制吞吐量。
(2)僅作用于新生代,對于需要考慮用戶交互等待時間的應用,可以考慮使用。

4、ConcurrentMarkSweep

即CMS,下面詳細說明。

5、G1

JDK7以后引入的,下面詳細說明。

(三)GC組合

以上各種GC算法可以自由組合用于新生代及老生代,JVM參數中提供了常用的組合參數。

1、-XX:+UseSerialGC

新:Serial,老:Serial Old。

2、-XX:+UseParNewGC

新:ParNew,老:Serial Old

3、-XX:+UseParallelGC

新:Parallel ,老:Serial Old

4、-XX:+UseParllelOldGC

新:Parallel, 老:Parallel Old

5、-XX:+UseConcMarkSweepGC

新:ParNew,老:CMS。
說明:當出現Concurrent Mode Failure或者Promotion Failed時,則會切換至ParNew + Serial Old組合。

6、-XX:+UseG1GC

G1收集器并發、并行執行GC。

下面詳細說一下目前最常用的幾個GC實現。

(四)ParNew

使用-XX:+UseConcMarkSweepGC時,ParNew是默認的YGC方式。

1、重要選項

(1)-XX:MaxTenuringThreshold
GC分代年齡設置,即經過多少次YGC后會被并提升到老生代,缺省值為15。
(2)-XX:UseAdaptiveSizePolicy
動態調整Java堆區各個區域的內存大小,以及GC分代年齡。
(3)-XX:ServivorRation
Eden/Sruvivor的空間比例,默認為8,即8:1:1。

2、日志說明

2016-10-28T20:04:48.613+0800: 10967.643: [GC2016-10-28T20:04:48.613+0800: 10967.643: [ParNew: 860597K->20467K(943744K), 0.0288630 secs] 1120868K->281132K(16672384K), 0.0290730 secs] [Times: user=0.41 sys=0.01, real=0.03 secs]

(1) 2016-10-28T20:04:48.613+0800是GC開始的時間,10967.643是進程啟動至今的時間。
(2)[ParNew: 860597K->20467K(943744K), 0.0288630 secs],這是YGC的情況,860597K表示YGC前新生代使用的內存空間,20467K是YGC后新生代的使用的內存空間,943744K是進程為新生代分配的空間。最后一個是指YGC花費的時間。
(3)1120868K->281132K(16672384K), 0.0290730 secs 意思與上面類似,但指的是事個堆的大小情況。上面可以看出YGC時回收了約840M的空間,因此堆被使用的空間也減少了840M左右。
(4) [Times: user=0.41 sys=0.01, real=0.03 secs] 三個時間分別是指用戶時間,系統時間以及實際的耗時。

(五)CMS

1、優缺點

先明白一個道理,只是標記階段是需要STW的,清理階段是不需要的,因為已經確定了某些對象是沒用的,對這些對象進行操作不會影響應用。因此CMS把并發階段分成了多個步驟,初始標記和最后的重新標記STW,而并發標記和并發預清理可以與用戶線程同時運行。

CMS通過細化標記階段,使得STW時間較短,但它有以下缺點。

(1)Concurrent Mode Failure
需要注意的是,CMS收集器無法處理浮動垃圾(Floating Garbage),可能出現“Concurrent Mode Failure”失敗而導致另一次Full GC的產生。由于CMS并發清理階段用戶線程還在運行著,伴隨程序的運行自然還會有新的垃圾不斷產生,這一部分垃圾出現在標記過程之后,CMS無法在本次收集中處理掉它們,只好留待下一次GC時再將其清理掉。這一部分垃圾就稱為“浮動垃圾”。也是由于在垃圾收集階段用戶線程還需要運行,即還需要預留足夠的內存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集,需要預留一部分空間提供并發收集時的程序運作使用。在默認設置下,CMS收集器在老年代使用了68%的空間后就會被激活,這是一個偏保守的設置,如果在應用中老年代增長不是太快,可以適當調高參數-XX:CMSInitiatingOccupancyFraction的值來提高觸發百分比,以便降低內存回收次數以獲取更好的性能。要是CMS運行期間預留的內存無法滿足程序需要,就會出現一次“Concurrent Mode Failure”失敗,這時候虛擬機將啟動后備預案:臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了。所以說參數-XX:CMSInitiatingOccupancyFraction設置得太高將會很容易導致大量“Concurrent Mode Failure”失敗,性能反而降低。

(2)內存碎片
還有一個缺點,CMS是一款基于“標記-清除”算法實現的收集器,這意味著收集結束時會產生大量空間碎片。空間碎片過多時,將會給大對象分配帶來很大的麻煩,往往會出現老年代還有很大的空間剩余,但是無法找到足夠大的連續空間來分配當前對象,不得不提前觸發一次Full GC。為了解決這個問題,CMS收集器提供了一個-XX:+UseCMSCompactAtFullCollection開關參數,用于在“享受”完Full GC服務之后額外免費附送一個碎片整理過程,內存整理的過程是無法并發的。空間碎片問題沒有了,但停頓時間不得不變長了。虛擬機設計者們還提供了另外一個參數-XX: CMSFullGCsBeforeCompaction,這個參數用于設置在執行多少次不壓縮的Full GC后,跟著來一次帶壓縮的。

2、CMS的基本流程

(1)初始標記:從根對象節點僅掃描與根節點直接關聯的對象并標記,這個過程必須STW,但由于根對象數量有限,所以這個過程很短暫。
(2)并發標記:與用戶線程并發執行,這個階段緊隨初始標記階段,在初始標記的基礎上繼續向下追溯標記。這個階段,應用線程與并發標記線程并發執行,所以應用不會停頓。
(3)并發預清理:與應用線程并發進行。由于上一個階段執行期間,會出現一些趁機提升至老生代的對象。在這個階段通過重新掃描,減少下一個階段重新標記的工作,因為下一個階段會STW。
(4)重新標記:STW,但很短暫。暫停工作線程,由GC線程掃描在CMS堆中的對象。這個過程主要是在前期標記的基礎上,僅對并發標記階段遭到破壞的對象引用關系進行修復。掃描從根開始。
(5)并發清理:清楚垃圾對象,這個階段GC線程和應用線程并發執行。
(6)并發重置:這個階段,重置CMS的數據結構,做好下一次執行GC的準備工作。
結合CMS的GC日志理解會更好,見下面。

3、CMS完整流程日志

從下面的流程可以看出CMS的FULL GC主要經歷以下幾個步驟:
(1)CMS-initial-mark

2016-10-28T22:45:24.755+0800: 20603.785: [GC [1 CMS-initial-mark: 12722006K(15728640K)] 12827206K(16672384K), 0.0058570 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

(2)CMS-concurrent-mark

2016-10-28T22:45:24.761+0800: 20603.791: [CMS-concurrent-mark-start]

2016-10-28T22:45:25.449+0800: 20604.480: [CMS-concurrent-mark: 0.686/0.689 secs] [Times: user=3.90 sys=0.15, real=0.69 secs]

(3)CMS-concurrent-preclean

2016-10-28T22:45:25.450+0800: 20604.480: [CMS-concurrent-preclean-start]

2016-10-28T22:45:25.483+0800: 20604.513: [CMS-concurrent-preclean: 0.033/0.033 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]

(3-1)CMS-concurrent-abortable-preclean

2016-10-28T22:45:25.483+0800: 20604.513: [CMS-concurrent-abortable-preclean-start] 2016-10-28T22:45:26.197+0800: 20605.228: [GC2016-10-28T22:45:26.197+0800: 20605.228: [ParNew: 943719K->104832K(943744K), 0.0307730 secs] 13671869K->12980931K(16672384K), 0.0310100 secs] [Times: user=0.33 sys=0.10, real=0.03 secs] 2016-10-28T22:45:26.814+0800: 20605.844: [CMS-concurrent-abortable-preclean: 1.197/1.331 secs] [Times: user=2.53 sys=0.21, real=1.33 secs] 2016-10-28T22:45:26.815+0800: 20605.845: [GC[YG occupancy: 527584 K (943744 K)]2016-10-28T22:45:26.815+0800: 20605.845: [GC2016-10-28T22:45:26.815+0800: 20605.845: [ParNew: 527584K->104832K(943744K), 0.0261780 secs] 13405732K->13077072K(16672384K), 0.0263780 secs] [Times: user=0.30 sys=0.06, real=0.02 secs]

(4)CMS-remark

2016-10-28T22:45:26.842+0800: 20605.872: [Rescan (parallel) , 0.0040910 secs]2016-10-28T22:45:26.846+0800: 20605.876: [weak refs processing, 0.0010700 secs]2016-10-28T22:45:26.847+0800: 20605.877: [scrub string table, 0.0007630 secs] [1 CMS-remark: 12972240K(15728640K)] 13077072K(16672384K), 0.0327240 secs] [Times: user=0.37 sys=0.06, real=0.03 secs]

(5)CMS-concurrent-sweep

2016-10-28T22:45:26.848+0800: 20605.878: [CMS-concurrent-sweep-start] 2016-10-28T22:45:28.025+0800: 20607.055: [GC2016-10-28T22:45:28.025+0800: 20607.055: [ParNew: 943510K->104832K(943744K), 0.0237830 secs] 10879313K->10153451K(16672384K), 0.0240310 secs] [Times: user=0.36 sys=0.00, real=0.02 secs] 2016-10-28T22:45:28.432+0800: 20607.463: [CMS-concurrent-sweep: 1.557/1.584 secs] [Times: user=3.46 sys=0.10, real=1.58 secs]

(6)CMS-concurrent-reset

2016-10-28T22:45:28.433+0800: 20607.463: [CMS-concurrent-reset-start] 2016-10-28T22:45:28.507+0800: 20607.537: [CMS-concurrent-reset: 0.074/0.074 secs] [Times: user=0.14 sys=0.05, real=0.08 secs]

完整的日志如下:

2016-10-28T22:45:24.755+0800: 20603.785: [GC [1 CMS-initial-mark: 12722006K(15728640K)] 12827206K(16672384K), 0.0058570 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 2016-10-28T22:45:24.761+0800: 20603.791: [CMS-concurrent-mark-start] 2016-10-28T22:45:25.449+0800: 20604.480: [CMS-concurrent-mark: 0.686/0.689 secs] [Times: user=3.90 sys=0.15, real=0.69 secs] 2016-10-28T22:45:25.450+0800: 20604.480: [CMS-concurrent-preclean-start] 2016-10-28T22:45:25.483+0800: 20604.513: [CMS-concurrent-preclean: 0.033/0.033 secs] [Times: user=0.03 sys=0.00, real=0.03 secs] 2016-10-28T22:45:25.483+0800: 20604.513: [CMS-concurrent-abortable-preclean-start] 2016-10-28T22:45:26.197+0800: 20605.228: [GC2016-10-28T22:45:26.197+0800: 20605.228: [ParNew: 943719K->104832K(943744K), 0.0307730 secs] 13671869K->12980931K(16672384K), 0.0310100 secs] [Times: user=0.33 sys=0.10, real=0.03 secs] 2016-10-28T22:45:26.814+0800: 20605.844: [CMS-concurrent-abortable-preclean: 1.197/1.331 secs] [Times: user=2.53 sys=0.21, real=1.33 secs] 2016-10-28T22:45:26.815+0800: 20605.845: [GC[YG occupancy: 527584 K (943744 K)]2016-10-28T22:45:26.815+0800: 20605.845: [GC2016-10-28T22:45:26.815+0800: 20605.845: [ParNew: 527584K->104832K(943744K), 0.0261780 secs] 13405732K->13077072K(16672384K), 0.0263780 secs] [Times: user=0.30 sys=0.06, real=0.02 secs] 2016-10-28T22:45:26.842+0800: 20605.872: [Rescan (parallel) , 0.0040910 secs]2016-10-28T22:45:26.846+0800: 20605.876: [weak refs processing, 0.0010700 secs]2016-10-28T22:45:26.847+0800: 20605.877: [scrub string table, 0.0007630 secs] [1 CMS-remark: 12972240K(15728640K)] 13077072K(16672384K), 0.0327240 secs] [Times: user=0.37 sys=0.06, real=0.03 secs] 2016-10-28T22:45:26.848+0800: 20605.878: [CMS-concurrent-sweep-start] 2016-10-28T22:45:28.025+0800: 20607.055: [GC2016-10-28T22:45:28.025+0800: 20607.055: [ParNew: 943510K->104832K(943744K), 0.0237830 secs] 10879313K->10153451K(16672384K), 0.0240310 secs] [Times: user=0.36 sys=0.00, real=0.02 secs] 2016-10-28T22:45:28.432+0800: 20607.463: [CMS-concurrent-sweep: 1.557/1.584 secs] [Times: user=3.46 sys=0.10, real=1.58 secs] 2016-10-28T22:45:28.433+0800: 20607.463: [CMS-concurrent-reset-start] 2016-10-28T22:45:28.507+0800: 20607.537: [CMS-concurrent-reset: 0.074/0.074 secs] [Times: user=0.14 sys=0.05, real=0.08 secs]

4、CMS的重要配置參數

(1)-XX:CMSInitiatingOccupancyFraction
觸發CMS Full GC時的堆使用比例,默認情況為68%。
如果設置過小,則會提高Full GC出現的頻率。
如果設置過大,則會有可能導致GC期間,old空間足以容納新生代提升上來的對象,出現Concurrent Mode Failure,這會觸發Serial Old進行Full GC。

(2)-XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0
上面說過,由于CMS會導致內存碎片,因此CMS提供了上面的第一個參數,指定每個Full GC后進行整理,但這需要STW,加大了STW時間。
因此作為折衷,CMS提供了第二個參數,指定每多少次Full GC后,才進行一個整理壓縮。

(3)-XX:+CMSParallelRemarkEnabled
表示并行remark

(4)-XX:+UseCMSInitiatingOccupancyOnly
表示只在到達閥值的時候,才進行CMS GC

(5)SoftRefLRUPolicyMSPerMB
官方解釋是softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap,我覺得沒必要等1秒,所以設置成0

(6)-XX:+CMSScavengeBeforeRemark
強制remark之前開始一次minor gc,減少remark的暫停時間,但是在remark之后也將立即開始又一次minor gc。

6、CMS一個常見的錯誤:concurrent mode failure

(concurrent mode failure): 13122360K->6441708K(15728640K), 223.2066850 secs] 13971757K->6441708K(16672384K), [CMS Perm : 61330K->61330K(131072K)], 223.2069760 secs] [Times: user=218.91 sys=0.10, real=223.22 secs]

基本原因為進程的CMS Full GC時發生concurrent mode failure,出現這種錯誤時CMS會中止GC,馬上轉向使用Serial Old進行Full GC,而使用Serial Old需要花費很長很長的時間,這個超長的時間有可能導致某些進程掛掉。

concurrent mode failure是在執行CMS GC的過程中同時有對象要放入舊生代,而此時舊生代空間不足造成的。

因此解決辦法就是避免在Full GC時,老生代放不下新生代promotion上來的對象,具體可操作的辦法包括:
1、【使用此方法】-XX:CMSInitiatingOccupancyFraction:降低觸發Full GC的閾值,默認為68%,這里設置為了80%。改加默認的68%。
2、減少新生代的大小。

完整GC日志:

2016-11-30T11:34:08.842+0800: 2832129.747: [GC [1 CMS-initial-mark: 12663697K(15728640K)] 12727632K(16672384K), 0.0131410 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 2016-11-30T11:34:08.885+0800: 2832129.790: [CMS-concurrent-mark-start] 2016-11-30T11:34:09.884+0800: 2832130.789: [GC2016-11-30T11:34:09.884+0800: 2832130.789: [ParNew: 893204K->99658K(943744K), 0.0707600 secs] 13583525K->12789979K(16672384K), 0.0710440 secs] [Times: user=0.66 sys=0.01, real=0.07 secs] 2016-11-30T11:34:10.786+0800: 2832131.691: [GC2016-11-30T11:34:10.786+0800: 2832131.691: [ParNew: 938570K->104832K(943744K), 0.1355030 secs] 13647323K->12889472K(16672384K), 0.1357800 secs] [Times: user=1.08 sys=0.01, real=0.14 secs] 2016-11-30T11:34:11.740+0800: 2832132.645: [CMS-concurrent-mark: 2.621/2.855 secs] [Times: user=22.88 sys=0.31, real=2.85 secs] 2016-11-30T11:34:11.740+0800: 2832132.645: [CMS-concurrent-preclean-start] 2016-11-30T11:34:11.921+0800: 2832132.826: [CMS-concurrent-preclean: 0.163/0.181 secs] [Times: user=0.64 sys=0.00, real=0.19 secs] 2016-11-30T11:34:11.921+0800: 2832132.826: [CMS-concurrent-abortable-preclean-start] 2016-11-30T11:34:11.961+0800: 2832132.866: [GC2016-11-30T11:34:11.961+0800: 2832132.866: [ParNew: 943744K->104832K(943744K), 0.1217300 secs] 13755008K->12985125K(16672384K), 0.1219930 secs] [Times: user=0.94 sys=0.00, real=0.12 secs] 2016-11-30T11:34:12.814+0800: 2832133.719: [CMS-concurrent-abortable-preclean: 0.762/0.893 secs] [Times: user=4.30 sys=0.06, real=0.89 secs] 2016-11-30T11:34:12.835+0800: 2832133.741: [GC[YG occupancy: 584557 K (943744 K)]2016-11-30T11:34:12.836+0800: 2832133.741: [GC2016-11-30T11:34:12.836+0800: 2832133.741: [ParNew (promotion failed): 584557K->567447K(943744K), 0.5155400 secs] 13473043K->13521212K(16672384K), 0.5157840 secs] [Times: user=0.93 sys=0.00, real=0.52 secs] 2016-11-30T11:34:13.352+0800: 2832134.257: [Rescan (parallel) , 1.9185140 secs]2016-11-30T11:34:15.270+0800: 2832136.175: [weak refs processing, 0.0004040 secs]2016-11-30T11:34:15.271+0800: 2832136.176: [scrub string table, 0.0011850 secs] [1 CMS-remark: 12953764K(15728640K)] 13521212K(16672384K), 2.4363850 secs] [Times: user=9.48 sys=0.07, real=2.44 secs] 2016-11-30T11:34:15.272+0800: 2832136.178: [CMS-concurrent-sweep-start] 2016-11-30T11:34:15.540+0800: 2832136.446: [Full GC2016-11-30T11:34:15.541+0800: 2832136.446: [CMS2016-11-30T11:35:03.411+0800: 2832184.317: [CMS-concurrent-sweep: 48.059/48.139 secs] [Times: user=12.80 sys=0.04, real=48.14 secs](concurrent mode failure): 12949885K->9366628K(15728640K), 110.8412530 secs] 13671217K->9366628K(16672384K), [CMS Perm : 85545K->85545K(142604K)], 110.8415460 secs] [Times: user=28.22 sys=0.03, real=110.86 secs] 2016-11-30T11:36:11.101+0800: 2832252.006: [GC2016-11-30T11:36:11.101+0800: 2832252.006: [ParNew: 838912K->62402K(943744K), 0.1140310 secs] 10213732K->9437222K(16672384K), 0.1142900 secs] [Times: user=0.43 sys=0.00, real=0.12 secs] 2016-11-30T11:36:17.830+0800: 2832258.735: [GC2016-11-30T11:36:17.830+0800: 2832258.735: [ParNew: 901314K->70061K(943744K), 0.1077270 secs] 10276134K->9444881K(16672384K), 0.1079440 secs] [Times: user=0.49 sys=0.01, real=0.11 secs] 2016-11-30T11:36:25.404+0800: 2832266.309: [GC2016-11-30T11:36:25.404+0800: 2832266.310: [ParNew: 908973K->73846K(943744K), 0.1772550 secs] 10283793K->9448667K(16672384K), 0.1774900 secs] [Times: user=0.66 sys=0.00, real=0.18 secs] 2016-11-30T11:36:32.468+0800: 2832273.373: [GC2016-11-30T11:36:32.468+0800: 2832273.373: [ParNew: 912758K->44006K(943744K), 0.1259630 secs] 10287579K->9418826K(16672384K), 0.1261750 secs] [Times: user=0.49 sys=0.00, real=0.13 secs] Heappar new generation total 943744K, used 505660K [0x00000003e0000000, 0x0000000420000000, 0x0000000420000000)eden space 838912K, 55% used [0x00000003e0000000, 0x00000003fc2d5818, 0x0000000413340000)from space 104832K, 41% used [0x00000004199a0000, 0x000000041c499950, 0x0000000420000000)to space 104832K, 0% used [0x0000000413340000, 0x0000000413340000, 0x00000004199a0000)concurrent mark-sweep generation total 15728640K, used 9374820K [0x0000000420000000, 0x00000007e0000000, 0x00000007e0000000)concurrent-mark-sweep perm gen total 142604K, used 85823K [0x00000007e0000000, 0x00000007e8b43000, 0x0000000800000000)

(六)G1

三、JVM重要參數

1、-Xmn[g|m|k]

或者使用: -XX:NewSize=[g|m|k] -XX:MaxNewSize=[g|m|k]
分別設置新生代的默認空間大小、最大空間大小,以及若二者相等時使用-Xmn代替。
老生代不需要單獨設置,用堆大小減去新生代及永久代大小即是老生代的大小

2、-Xms -Xmx

-Xms:初始堆大小 -Xmx:最大堆大小,默認值為物理內存的1/4
默認(MinHeapFreeRatio參數可以調整)空余堆內存小于40%時,JVM就會增大堆直到-Xmx的最大限制。默認(MaxHeapFreeRatio參數可以調整)空余堆內存大于70%時,JVM會減少堆直到 -Xms的最小限制。
上面指定的空間大小為新老生代所共用,默認情況下JVM可以根據應用程序的需要動態的擴展或者收縮。
關注吞吐量及延遲的應用程序應該將-Xms與-Xmx設定為同一值。這是因為無論擴展還是收縮新生代或者老生代空間都要進行Full GC。

3、-XX:PermSize=[g|m|k] -XX:MaxPermSize=[g|m|k]

用于設置永久代的空間大小。

4、-Xss

-Xss128k:設置每個線程的堆棧大小。JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。更具應用的線程所需內存大小進行調整。在相同物理內存下,減小這個值能生成更多的線程。但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。

5、 -XX:NewRatio -XX:SurvivorRatio

  • -XX:NewRatio=4:設置年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)。設置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5
  • -XX:SurvivorRatio=4:設置年輕代中Eden區與Survivor區的大小比值。設置為4,則兩個Survivor區與一個Eden區的比值為2:4,一個Survivor區占整個年輕代的1/6

6、client與server模式

-client:把應用當成客戶端類程序進行優化。該選項應該在應用啟動時使用,對這類應用程序而言,內存占用是最重要的性能標準,遠比高吞吐量重要。
-server:把應用當成服務器類程序進行優化。適用于高吞吐量比啟動時間和內存占用更重要的應用程序。
目前還有一個較新的選項:
-server -XX:TieredCompilation:結合了二者的優點,可以考慮代替-client。

7、-32與-64

使用32位JVM還是64位JVM由應用程序使用的內存來決定,基本原則如下:
0~2G:32位
2G~32G:使用-d64 -XX:+UserCompressedOops
32G以上:64位
事實上,在Java6 Update18之后,JVM根據堆大小自動啟用-XX:+UserCompressedOops,因此配置時2G以內使用-32,2G以上使用-64即可。

8、GC日志打印相關

-XX:+PrintGCDetails:打印GC詳細信息
-XX:+PrintGC:打印GC基礎信息
+XX:PrintGCTimeStamps/–XX:PrintGCDateStamps:開始執行的時間(基準時間/日期時間)
-XX:PrintGCApplicationStoppedTime:打印GC造成程序暫停的時間
-XX:PrintTLAB:打印TLAB空間的使用情況
-XX:PrintTenuringDistribution:打印每次YGC后新的存活周期的閾值
-XX:+PrintHeapAtGC:打印GC前后詳細的堆棧信息
-Xloggc:指定GC日志的輸出路徑

示例
-Xloggc:/home/lujinhong/jvm/gc-$(date +%Y%m%d-%H%M%S).log -XX:+PrintGCDetails -XX:+PrintGCDateStamps

四、常用工具及命令

(一)最常用命令

jstat -gcutil 10763 1000 100 (顯示百分比)
jstat -gc 10763 1000 100 (顯示實際大小,單位為k)
jstack -l 48150 >> 1.txt
jmap -dump:file=1.txt 48150 (然后使用ibm HeapAnalyzer分析結果)
jmap -heap 15914

(二)常用命令

1、jps

顯示java進程,即使用java命令啟動的進程
常用用法
1、jps:顯示進程id與進程名稱
2、jps -l:顯示主類的全名,如果進程執行的是jar包,則輸出Jar路徑
3、jps -v:輸出JVM參數

hadoop@gdc-dn06-formal:~$ jps -lv | grep -i datanode
48150 org.apache.hadoop.hdfs.server.datanode.DataNode -Dproc_datanode -Xmx4096m -Dhadoop.log.dir=/home/hadoop/logs -Dhadoop.log.file=hadoop-hadoop-datanode-gdc-dn06-formal.i.nease.net.log -Dhadoop.home.dir=/home/hadoop/hadoop -Dhadoop.id.str=hadoop -Dhadoop.root.logger=INFO,RFA -Djava.library.path=/home/hadoop/hadoop/lib/native -Dhadoop.policy.file=hadoop-policy.xml -Djava.net.preferIPv4Stack=true -Dlog4j.configuration=log4j_dn.properties -Xmx20480m -Dcom.sun.management.jmxremote -XX:+UseConcMarkSweepGC -XX:-TraceClassUnloading -Dcom.sun.management.jmxremote.port=65302 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -XX:ErrorFile=/home/hadoop/logs/error.log -Dhadoop.security.logger=INFO,RFAS

2、jstat

虛擬機統計信息監視工具

監視gc相關的信息,監控進程10763,每1秒一次,共100次

(1) jstat -gcutil 10763 1000 100

S0 S1 E O P YGC YGCT FGC FGCT GCT3.52 0.00 29.59 35.64 66.87 3382 675.691 2 0.074 675.7653.52 0.00 35.33 35.64 66.87 3382 675.691 2 0.074 675.7653.52 0.00 41.80 35.64 66.87 3382 675.691 2 0.074 675.7653.52 0.00 47.07 35.64 66.87 3382 675.691 2 0.074 675.7653.52 0.00 51.52 35.64 66.87 3382 675.691 2 0.074 675.7653.52 0.00 60.17 35.64 66.87 3382 675.691 2 0.074 675.7653.52 0.00 73.33 35.64 66.87 3382 675.691 2 0.074 675.7653.52 0.00 85.25 35.64 66.87 3382 675.691 2 0.074 675.7653.52 0.00 96.02 35.64 66.87 3382 675.691 2 0.074 675.7650.00 3.84 5.77 35.64 66.87 3383 675.717 2 0.074 675.7910.00 3.84 11.55 35.64 66.87 3383 675.717 2 0.074 675.7910.00 3.84 18.43 35.64 66.87 3383 675.717 2 0.074 675.7910.00 3.84 31.36 35.64 66.87 3383 675.717 2 0.074 675.791

各個列的意思是
* S0 : S0的使用率
* S1 : S1的使用率。重復一下(詳見上面),新生代分為eden,S0, S1三個區域,對象首先分配在eden區,然后經過young GC后放入S0或者S1(二者輪流使用),經過幾次young GC還存活的對象會被放到老生代。
* E:eden的使用率。注意到上面第9~10行之間發生了一次young GC,因此當時E還存活的對象被放到了S1,其余對象被清除,同時,S0的對象也到了S1,S0的使用率恢復到了0.
* O : 老生代的使用率。
* YGC:進程起來后到現來發生的YGC次數。
* YGCT:YGC總共花費的時間。因此每次YGC的時間為675.717/3383.時間為秒
* FGC:進程起來后到現來發生的FGC次數。
* FGCT:FGC總共花費的時間。因此每次FGC花費的時間為0.074/2
* GCT:進程起來后到現在GC的總花費時間。

(2)jstat -gc 27787 1000 10

S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 39296.0 39296.0 23829.0 0.0 314624.0 88632.7 655360.0 582906.8 131072.0 43506.3 289764 1539.501 1060 60.341 1599.842 39296.0 39296.0 0.0 21878.3 314624.0 213984.4 655360.0 582939.7 131072.0 43506.3 289765 1539.507 1060 60.341 1599.848 39296.0 39296.0 0.0 17420.6 314624.0 26928.7 655360.0 582989.0 131072.0 43506.3 289767 1539.518 1060 60.341 1599.859 39296.0 39296.0 14004.3 0.0 314624.0 167322.2 655360.0 583013.3 131072.0 43506.3 289768 1539.523 1060 60.341 1599.864 39296.0 39296.0 0.0 11592.4 314624.0 309165.1 655360.0 583038.1 131072.0 43506.3 289769 1539.528 1060 60.341 1599.869 39296.0 39296.0 0.0 2172.4 314624.0 134507.1 655360.0 588566.0 131072.0 43506.3 289771 1539.539 1060 60.341 1599.880 39296.0 39296.0 564.6 0.0 314624.0 106047.3 655360.0 588569.4 131072.0 43506.3 289772 1539.542 1060 60.341 1599.883

這里顯示的是實際大小,單位是k,上面-gcutil顯示的是百分比。

3、jinfo

java配置信息工具,顯示jvm參數,類似于jps -v
hadoop@gdc-dn06-formal:~$ jinfo -flags 48150
Attaching to process ID 48150, please wait…
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04

-Dproc_datanode -Xmx4096m -Dhadoop.log.dir=/home/hadoop/logs -Dhadoop.log.file=hadoop-hadoop-datanode-gdc-dn06-formal.i.nease.net.log -Dhadoop.home.dir=/home/hadoop/hadoop -Dhadoop.id.str=hadoop -Dhadoop.root.logger=INFO,RFA -Djava.library.path=/home/hadoop/hadoop/lib/native -Dhadoop.policy.file=hadoop-policy.xml -Djava.net.preferIPv4Stack=true -Dlog4j.configuration=log4j_dn.properties -Xmx20480m -Dcom.sun.management.jmxremote -XX:+UseConcMarkSweepGC -XX:-TraceClassUnloading -Dcom.sun.management.jmxremote.port=65302 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -XX:ErrorFile=/home/hadoop/logs/error.log -Dhadoop.security.logger=INFO,RFAS

4、jmap 與 jhat結合使用:java內存映像工具與分析工具

jmap:將Jvm中的對象dump下來,準備給jhat分析。
jhat: 虛擬機堆轉儲快照分析工具。一直不成功,使用IBM HeapAnalyzer很方便。

簡單步驟

$ jmap -dump:format=b,file=heamdump.out 進程號

詳細說明如下:
為了分析java應用的內存泄漏,使用thread dump往往解決不了問題。使用jstat【eg:jstat -gcutil pid 1000 5】工具查看運行的java應用的heap size,perm size ,survivor ratio等,當時你無法知道是什么對象把堆填滿了。

什么是 Java heap dump

首先需要搞懂什么是java heap,java heap是分配給實例類和數組對象運行數據區,所有java線程在運行期間共享heap中的數據。Java heap dump相當于java應用在運行的時候在某個時間點上打了個快照(snapshot)。

觸發 Java heap dump的方法

  • 使用$JAVA_HOME/bin/jmap -dump來觸發,eg:jmap -dump:format=b,file=heamdump.out 進程號
  • 在應用啟動時配置相關的參數 -XX:+HeapDumpOnOutOfMemoryError,當應用拋出OutOfMemoryError時生成dump文件。
  • 使用$JAVA_HOME/bin/jcosole中的MBean,到MBean>com.sun.management>HotSpotDiagnostic>操作>dumpHeap中,點擊 dumpHeap按鈕。生成的dump文件在java應用的根目錄下面。
  • 使用hprof。啟動虛擬機加入-Xrunhprof:head=site,會生成java.hprof.txt文件。該配置會導致jvm運行非常的慢,不適合生產環境。

分析 Java heap dump

  • 使用IBM HeapAnalyzer

    IBM HeapAnalyzer是一款免費的JVM內存堆的圖形分析工具,它可以有效的列舉堆的內存使用狀況,幫助分析Java內存泄漏的原因。使用很簡單,先下載一個jar包,然后運行:

    java -Xmx512m -jar ha456.jar heapdump.out

下載地址:https://www.ibm.com/developerworks/community/groups/service/html/communityview?communityUuid=4544bafe-c7a2-455f-9d43-eb866ea60091
速度太慢時還可以通過csdn等下載

可以不加最后一個參數,此時只打開軟件,然后在UI中打開dump文件即可。
注意-Xmx中的-符號是英文的

  • jhat

    jhat(Java Head Analyse Tool )是用來分析java堆的命令,可以將堆中的對象以html的形式顯示出來,包括對象的數量,大小等等,并支持對象查詢語言OQL,分析相關的應用后,可以通過http://localhost:7000來訪問分析結果。

    示例: $JAVA_HOME/bin/jhat -J-Xmx512m dump.out

  • Eclipse MemoryAnalyzer

    Eclipse Memory Analyzer是一個快速并且功能強大的Java heap分析器,能夠幫助你查找內存泄漏和減少內存消耗。在File>Acquire Heap Dump>configure>HPROF jmap dump provider設置一下分析應用的JDK,點擊相關應用列表來生成heap dump并分析。

    在socket,nio中的有些API中,申請的內存是直接想OS要的,在堆中分析內存是查看不到的,可以通過-XX:MaxDirectMemorySize=來設置應用向OS直接申請的最大內存數。

5、jmap的其它用法

(1)jmap -heap 15914

打印heap空間的概要,這里可以粗略的檢驗heap空間的使用情況。

輸出很簡單,第四行起開始輸出此進程的JAVA使用的環境。

Heap Configuration:指java應用啟動時設置的JVM參數。像最大使用內存大小,年老代,年青代,持久代大小等。

Heap Usage:當時的heap實際使用情況。包括新生代、老生代和持久代。

其中新生代包括:Eden區的大小、已使用大小、空閑大小及使用率。Survive區的From和To同樣。

有這個可以很簡單的查看本進程的內存使用情況。

可以用于分析堆內存分區大小是否合理,新生代和老生代的大小分配是否合適等。

也許進程占用的總內存比較多,但我們在這里可以看到真正用到的并沒有多少,很多都是”Free”。內存使用的堆積大多在老年代,內存池露始于此,所以要格外關心“Old Generation”。

注意 oldsize表示的是老生代的初始大小,不是實際大小

hadoop@gdc-storm07-storm:~/var$ jmap -heap 15914 Attaching to process ID 15914, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.65-b04using parallel threads in the new generation. using thread-local object allocation. Concurrent Mark-Sweep GCHeap Configuration:MinHeapFreeRatio = 40MaxHeapFreeRatio = 70MaxHeapSize = 1073741824 (1024.0MB)NewSize = 402653184 (384.0MB)MaxNewSize = 402653184 (384.0MB)OldSize = 5439488 (5.1875MB)NewRatio = 2SurvivorRatio = 8PermSize = 134217728 (128.0MB)MaxPermSize = 134217728 (128.0MB)G1HeapRegionSize = 0 (0.0MB)Heap Usage: New Generation (Eden + 1 Survivor Space):capacity = 362414080 (345.625MB)used = 124813128 (119.03107452392578MB)free = 237600952 (226.59392547607422MB)34.43937056750113% used Eden Space:capacity = 322174976 (307.25MB)used = 120391536 (114.81431579589844MB)free = 201783440 (192.43568420410156MB)37.36836966506052% used From Space:capacity = 40239104 (38.375MB)used = 4421592 (4.216758728027344MB)free = 35817512 (34.158241271972656MB)10.988296359680374% used To Space:capacity = 40239104 (38.375MB)used = 0 (0.0MB)free = 40239104 (38.375MB)0.0% used concurrent mark-sweep generation:capacity = 671088640 (640.0MB)used = 342857688 (326.97457122802734MB)free = 328230952 (313.02542877197266MB)51.08977675437927% used Perm Generation:capacity = 134217728 (128.0MB)used = 54027416 (51.524559020996094MB)free = 80190312 (76.4754409790039MB)40.2535617351532% used

(2)jmap -histo 15914

hadoop@gdc-storm07-storm:~/var$ jmap -histo 24203 | head

num #instances #bytes class name ----------------------------------------------1: 42048 10496784 [B2: 260 9596320 [I3: 57091 6181096 [C4: 19351 2555984 <constMethodKlass>5: 19351 2485600 <methodKlass>6: 1748 1925064 <constantPoolKlass>7: 1748 1219504 <instanceKlassKlass>

這里會生成一個類的統計報表,此表非常簡單,如顯示什么類有多少個實例,共占了多少字節等。

其中關于I、B、C等的說明如下

BaseType Character Type Interpretation B byte signed byte C char Unicode character D double double-precision floating-point value F float single-precision floating-point value I int integer J long long integer L<classname>; reference an instance of class de><classname>de> S short signed short Z boolean de>truede> or de>falsede> [ reference one array dimension

6、jstack

java堆棧跟蹤工具
查看各個線程信息
jstack?l48150>>2.txthadoop@gdc?dn06?formal:? more 2.txt
2015-05-24 11:16:27
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.65-b04 mixed mode):

“DataXceiver for client DFSClient_NONMAPREDUCE_1067049541_1 at /10.160.254.91:59578 [Sending block BP-1320426528-10.120.75.79-136177508
6190:blk_1545471492_1100790319712]” daemon prio=10 tid=0x00007ff12cc5b000 nid=0xa424 runnable [0x00007ff135594000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
- locked <0x00000003017d1f88> (a sun.nio.ch.Util2)?locked<0x00000003017d1f78>(ajava.util.CollectionsUnmodifiableSet)

(三)使用visualvm遠程監控java進程(以hadoop進程為例)

1、下載安裝
(1)下載visualvm
在官網上下載即可,有mac版
(2)工具—插件,選擇感興趣的插件進行安裝
此時若本地有運行java進程,則在本地那里已經可以進行監控分析

2、遠程服務器配置
(1)在任意目錄建立文件jstatd.all.policy,內容如下:
grant codebase “file:${java.home}/../lib/tools.jar” {
permission java.security.AllPermission;
};

3、運行jstad服務
nohup jstatd -J-Djava.security.policy=jstatd.all.policy &
默認是以1099端口運行

4、連接遠程監控
遠程—添加jstatd連接,填入ip地址即可

(四)使用gcviewer分析GC日志

使用PrintGCDetail生成的GC日志通常很大,肉眼很難分析出一些有用的結論,因此需要GUI工具來協助。
最有用的應該是java自身提供的gchisto,但這個工具已經很久沒更新了,對于一些新的GC類型支持不好,甚至連ParNew都支持不好,因此我們選用gcviewer。

使用非常簡單,下載,然后add log文件進去。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的Java内存组成GC算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。