JVM參數

常見參數

java啓動參數

參數 說明
- 所有jvm實現都必須實現這些參數的功能,向後兼容
-X 默認jvm實現這些參數的功能,不保證所有jvm實現都滿足,不保證向後兼容
-XX 各個jvm實現有所不同,可能會隨時取消

輸出jvm的信息參數

參數 說明
-verbose:gc 輸出每次GC的相關信息
-XX:+PrintGCDetails 獲取的信息比上面更多

更多信息

參數 說明
-XX:PrintGCTimeStamps 顯示jvm啓動到執行GC時流逝的時間,單位是秒
-XX:PrintDateTimeStamps 顯示執行GC時的本地時間(Java 6 update 4纔開始支持)
-Xloggc:/Users/cc/Desktop/log.txt gc信息重定向到文件

解讀log信息

CommandLine flags: -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=2147483648 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC 
0.465: [GC (System.gc()) [PSYoungGen: 5341K->851K(38400K)] 5341K->859K(125952K), 0.0020406 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
0.467: [Full GC (System.gc()) [PSYoungGen: 851K->0K(38400K)] [ParOldGen: 8K->778K(87552K)] 859K->778K(125952K), [Metaspace: 3653K->3653K(1056768K)], 0.0064182 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 38400K, used 1553K [0x0000000795580000, 0x0000000798000000, 0x00000007c0000000)
  eden space 33280K, 4% used [0x0000000795580000,0x00000007957045f8,0x0000000797600000)
  from space 5120K, 0% used [0x0000000797600000,0x0000000797600000,0x0000000797b00000)
  to   space 5120K, 0% used [0x0000000797b00000,0x0000000797b00000,0x0000000798000000)
 ParOldGen       total 87552K, used 778K [0x0000000740000000, 0x0000000745580000, 0x0000000795580000)
  object space 87552K, 0% used [0x0000000740000000,0x00000007400c2ab8,0x0000000745580000)
 Metaspace       used 3775K, capacity 4888K, committed 5120K, reserved 1056768K
  class space    used 419K, capacity 456K, committed 512K, reserved 1048576K
System.out.println(Runtime.getRuntime().maxMemory());           System.out.println(Runtime.getRuntime().freeMemory());          System.out.println(Runtime.getRuntime().totalMemory());

JVM內存結構

這裏寫圖片描述
JVM的內存由棧寄存器和堆構成,堆裏面有新生代、老年代和持久代。

Young(年輕代)

分爲Eden(伊甸)區,兩個survivor(存活)區。大部分對象(剛new出的對象)在Eden區,當Eden區滿時,還存貨的對象被複制到survivor區中的一個,當這個survivor區滿時,此區的存活對象將被複制到另外一個survivor區,當這個survivor區滿時,從第一個survivor區複製過來的並且此時還存活的對象,被複制到“老年代”。survivor總有一個是空的。

Tenured(老年代)

老年代存放從年輕代存活的對象,一般來說老年代存放的都是生命週期較長的對象

Perm(持久代)

用於存放靜態文件,如java類,方法。持久代對垃圾回收沒有顯著影響.final修飾的常量,classLoader加載的信息。

GC的兩種類型

ScavengeGC(Minor GC) Full GC
一般情況下,當新對象生成並且在Eden申請空間失敗時,觸發scavengeGC,堆Eden區域進行GC,清楚非存活對象,並將尚且存活的對象移動到survivor區,然後整理survivor的兩個區 對整個堆進行真理,包括young tenured和perm。
觸發:Eden區滿 觸發full gc的三種原因:tenured被寫滿;perm被寫滿;System.gc()被顯式調用
新生代發生的垃圾回收操作,因爲java對象大多具有朝生夕滅的特性,所以minorGC非常頻繁,一般回收速度也比較快,通常在百毫秒級 老年代GC(FullGC/MajorGC)發生在老年代的GC,出現了MajorGC經常會伴隨至少一次的MinorGC(非絕對,在parallelscavenge收集器的手機策略裏就有直接進行majorGC的策略選擇過程)。majorGC的速度一般會比MinorGC慢10倍以上,1.4G的Old Gen進行一次回收通常需要20-40秒
首次YGC:對Eden區進行垃圾回收,回收後Eden區中依然存活的對象被移入S0 第二次YGC:將s0中的對象複製到s1,並對Eden區和s1進行垃圾回收,回收後Eden區依然存活的對象被移入s1,並將s0中所有的對象清楚,以此類推,在S0/S1中存活次數超過N次(默認15次)的對象移入OldGen,如果S0/S1空間不足,則直接移入Old Gen 對young gen,old gen,perm gen進行一次完整的垃圾回收,old gen不在被引用的對象直接銷燬,young gen的回收算法同youngGC,perm GEM回收方式爲,如果堆中不存在某個類的任何勢力,且該類的Class對象沒有在任何地方被引用,則該類被回收

虛擬機給每個對象定義了一個對象年齡(Age)計數器,如果對象在Eden出生並經過第一次MinorGC後仍然存活,並且能被survivor容納的話,將被移動到survivor空間中,並將對象年齡設爲1.對象在survivor區中每熬過一次MinorGC,年齡就增加一歲,當它的年齡增加到一定程度(默認爲15歲)時,就會被晉升到老年代中。對象晉升老年代的年齡閾值 通過-XX:MaxTenuringThreshhold來設置

jstat -gcutil <pid> <timediff>

用jstat查看jvm內存使用情況

s0 s1 E O P YGC YGCT FGC FGCT GCT
S0區佔用的空間比 s1 Eden區 Old區 Perm區 YGC的次數 YGCtime從程序啓動到採用ygc所有的時間/s FGC次數 FGC時間/s 用於垃圾回收的總時間/s
xiejiangqiongdeMacBook-Pro:~ cc$ jstat -gcutil 5061 1000
Warning: Unresolved Symbol: sun.gc.generation.2.space.0.capacity substituted NaN
Warning: Unresolved Symbol: sun.gc.generation.2.space.0.used substituted NaN
Warning: Unresolved Symbol: sun.gc.generation.2.space.0.capacity substituted NaN
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   
 75.66   0.00   0.00  99.7618    2.212     5    2.398    4.610
 73.66   0.00  20.00  65.5818    2.212     5    4.433    6.645
 73.66   0.00  44.00  65.5818    2.212     5    4.433    6.645
 73.66   0.00  64.00  65.5818    2.212     5    4.433    6.645
 73.66   0.00  84.00  65.5818    2.212     5    4.433    6.645
 73.66   0.00 100.00  65.5818    2.212     5    4.433    6.645
  0.00 100.00   8.00  68.2319    2.613     5    4.433    7.046
  0.00 100.00  32.00  68.2319    2.613     5    4.433    7.046
  0.00 100.00  50.00  68.2319    2.613     5    4.433    7.046
  0.00 100.00  68.00  68.2319    2.613     5    4.433    7.046
  0.00 100.00  86.00  68.2319    2.613     5    4.433    7.046
  2.72 100.00 100.00  81.5520    2.613     5    4.433    7.046
 51.81   0.00   0.00  88.7020    3.010     6    4.433    7.443
  5.87   0.00   2.00  69.1620    3.010     6    6.121    9.130
  5.87   0.00  30.00  69.1620    3.010     6    6.121    9.130
  5.87   0.00  54.00  69.1620    3.010     6    6.121    9.130

ps -ef | grep java 查看待檢測進程的id

uid pid ppid c stime tty cmd
用戶ID 進程ID 父進程ID 開始時間 登錄方式 命令

從我的畢設中大量的FullGC看內存

內存泄露時會發生什麼

  1. 某些對象會佔用大量的JVM內存,且長時間無法被回收掉。這些長時間無法被回收的對象通常都會在Old Gen中
  2. 由於Old Gen中存在大量無法被回收的對象,每次FullGC只能釋放出極少的Old Gen空間,回收處的這少部分Old Gen空間又會很快被佔滿,這就會導致JVM在頻繁地進行FullGC
  3. FullGC很慢,而JVM在做GC時會stop-the-world,在GC時終止JVM的一切工作。所以假設在內存泄露發生時,JVM被迫每40秒做一次FullFC,每次FullGC需要30秒,這就代表JVM只有1/4的時間在正常工作,此時的性能一定是非常慢的
  4. 而隨着泄露對象的不斷增加,OldGen的可用空間會越來越少,最終JVM會回收不出足夠的可用內容以支撐程序的運行,從而導致服務的徹底不可用

通過jstat觀察Old Gen內存佔用的增長速度,以及GC的頻次

  • 如果jstat命令輸出的信息表示JVM正在頻繁進行FullGC,那麼基本而已肯定性能故障的原因是內存泄露

    [Full GC (Ergonomics) 3344336K->3068858K(3749376K), 3.7187515 secs]
    [Full GC (Ergonomics) 3344336K->3091406K(3749376K), 3.2715931 secs]
    [Full GC (Ergonomics) 3344336K->3112195K(3749376K), 3.9227456 secs]
    [Full GC (Ergonomics) 3344336K->3139728K(3749376K), 3.5998555 secs]

參考博客

日誌信息解讀
IDEA JVM運行參數
JVM參數原理和性能調優
jvm調優總結+jstat分析 很好的總結
java gc的工作原理 minor gc full gc的原理
關於tomcat上的性能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章