JVM堆內存設置和測試

首先Java虛擬機中gc的原理,能夠參見
http://www.360doc.com/content/12/1023/16/9615799_243296263.shtml
http://ifeve.com/useful-jvm-flags-part-5-young-generation-garbage-collection/
如下是一些我的總結和測試。 html

1. Java虛擬機內存結構

劃分新生代和老年代,這樣只在新生代分配內存,從而簡化了新對象的分配。另外新生代和老年代使用不一樣的GC算法,能夠更有效的清除再也不須要的對象。
從上圖能夠看出,JVM內存由young+old+permanent組成,JVM又進一步將Young分紅了eden,from survivor和to survivor三個區域。新對象會首先分配在 Eden 中(若是新對象過大,會直接分配在老年代中)。在GC中,Eden 中的對象會被移動到survivor中,直至對象熬過必定的GC的次數,會被移動到老年代。老年代通常是一些系統級(線程庫,classloader等) 的對象,官方推薦新生代佔堆大小的3/8,而survivor區各佔新生代的1/10。 java

2. GC原理

jvm_mem
不少對象的生存時間都很短,而新生對象不多引用生存時間長的對象。因此,GC會頻繁訪問新生代對象,執行Minor GC。在新生代中,GC能夠快速標記回收」死對象」,而不須要掃描整個Heap中的存活一段時間的」老對象」(即執行major/FULL GC)。
新生代的GC使用複製算法。在GC前To survivor區保持清空,對象保存在Eden和From survivor區中,GC運行時,Eden中的倖存對象被複制到 To survivor區。針對 From survivor取中的倖存對象,會考慮對象年齡,若是年齡沒達到閥值(tenuring threshold),對象會被複制到To survivor區。若是達到閥值對象被複制到老年代。複製階段完成後,Eden 和From survivor區中只保存死對象,能夠被視爲所有清空。若是在複製過程當中To survivor區被填滿了,剩餘的對象會被複制到老年代中。最後 From和To會對換。
young_gc
上圖演示GC過程,黃色表示死對象,綠色表示剩餘空間,紅色表示倖存對象
若是新生代太小,會致使新生對象很快就晉升到老年代中,在老年代中對象很難被回收。若是新生代過大,會發生過多的複製過程。因此須要經過不斷的測試調優,找到一個合適的JVM參數。 算法

3. JVM內存參數

堆內存大小設置

-Xms:初始堆大小。只要啓動,就佔用的堆大小
-Xmx:最大堆大小。java.lang.OutOfMemoryError: Java heap這個錯誤能夠經過配置-Xms和-Xmx參數來設置
-Xss:棧大小分配。棧是每一個線程私有的區域,一般只有幾百K大小,決定了函數調用的深度,而局部變量、參數都分配到棧上。當出現大量局部變量,遞歸時,會發生棧空間OOM(java.lang.StackOverflowError)之類的錯誤。
-XX:NewSize=n:設置新生代大小的絕對值
-XX:NewRatio=n: 設置年輕代和年老代的比值。好比設置爲3,則新生代:老年代=1:3,新生代佔1/4的總heap大小。
-XX:SurvivorRatio=n:年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有from和to兩個。好比設置爲8時,那麼eden:from:to=8:1:1
-XX:MaxPermSize=n:設置持久代大小 ;java.lang.OutOfMemoryError: PermGen space這個OOM錯誤須要合理調大PermSize和MaxPermSize大小。
-XX:HeapDumpOnOutOfMemoryError:發生OOM時轉儲堆到文件,這是一個很是好的診斷方法。
-XX:HeapDumpPath:導出堆的轉儲文件路徑
-XX:OnOutOfMemoryError:OOM時,執行一個腳本,好比發送郵件報警,重啓程序。後面跟着一個腳本的路徑。 jvm

測試1

第一次分配5M,沒有超過xms。第二次再次分配5M,total mem會增長。第三次再申請40M,超過xmx限制因此報了OOM錯誤。 函數

public class JVMTest { public static void main(String args[]) { //=====================Begin========================= System.out.print("Xmx="); System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M"); System.out.print("free mem="); System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M"); System.out.print("total mem="); System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M"); //=====================First Allocated========================= System.out.println("5MB array allocated"); byte[] b1 = new byte[5 * 1024 * 1024]; System.out.print("Xmx="); System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M"); System.out.print("free mem="); System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M"); System.out.print("total mem="); System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M"); //=====================Second Allocated========================= System.out.println("10MB array allocated"); byte[] b2 = new byte[10 * 1024 * 1024]; System.out.print("Xmx="); System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M"); System.out.print("free mem="); System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M"); System.out.print("total mem="); System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M"); //=====================OOM========================= System.out.println("OOM!!!"); System.gc(); byte[] b3 = new byte[40 * 1024 * 1024]; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class JVMTest {
     public static void main ( String args [ ] ) {
 
         //=====================Begin=========================
         System . out . print ( "Xmx=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . maxMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         System . out . print ( "free mem=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . freeMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         System . out . print ( "total mem=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . totalMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         //=====================First Allocated=========================
         System . out . println ( "5MB array allocated" ) ;
         byte [ ] b1 = new byte [ 5 * 1024 * 1024 ] ;
 
         System . out . print ( "Xmx=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . maxMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         System . out . print ( "free mem=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . freeMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         System . out . print ( "total mem=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . totalMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         //=====================Second Allocated=========================
         System . out . println ( "10MB array allocated" ) ;
         byte [ ] b2 = new byte [ 10 * 1024 * 1024 ] ;
 
         System . out . print ( "Xmx=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . maxMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         System . out . print ( "free mem=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . freeMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         System . out . print ( "total mem=" ) ;
         System . out . println ( Runtime . getRuntime ( ) . totalMemory ( ) / 1024.0 / 1024 + "M" ) ;
 
         //=====================OOM=========================
         System . out . println ( "OOM!!!" ) ;
         System . gc ( ) ;
         byte [ ] b3 = new byte [ 40 * 1024 * 1024 ] ;
     }
}

以50m XMX和10m XMS的運行測試: 測試

D:\>java -Xmx50m -Xms10m JVMTest Xmx=44.5M free mem=9.804550170898438M total mem=10.5M 5MB array allocated Xmx=44.5M free mem=4.804534912109375M total mem=10.5M 10MB array allocated Xmx=44.5M free mem=5.3045196533203125M total mem=21.0M OOM!!! Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at JVMTest.main(JVMTest.java:43)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
D : \ > java - Xmx50m - Xms10m JVMTest
Xmx = 44.5M
free mem = 9.804550170898438M
total mem = 10.5M
5MB array allocated
Xmx = 44.5M
free mem = 4.804534912109375M
total mem = 10.5M
10MB array allocated
Xmx = 44.5M
free mem = 5.3045196533203125M
total mem = 21.0M
OOM ! ! !
Exception in thread "main" java . lang . OutOfMemoryError : Java heap space
         at JVMTest . main ( JVMTest . java : 43 )

測試2

public class JVMXmn1 { public static void main(String args[]) { byte[] b=null; for(int i=0;i<10;i++) b=new byte[1*1024*1024]; } }
1
2
3
4
5
6
7
public class JVMXmn1 {
     public static void main ( String args [ ] ) {
         byte [ ] b = null ;
         for ( int i = 0 ; i < 10 ; i ++ )
             b = new byte [ 1 * 1024 * 1024 ] ;
     }
}

下面按1m的新生代設置,這時對象大於新生代大小,會直接建立在老年代。新生代沒有使用。沒有觸發gc 優化

D:\>java -Xmx20m -Xms20m -Xmn1m -XX:+PrintGCDetails JVMXmn1 Heap PSYoungGen total 512K, used 0K [0x00000000fff00000, 0x0000000100000000, 0x0000000100000000) eden space 0K, -2147483648% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff00000) from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000) to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000) ParOldGen total 19456K, used 10836K [0x00000000fec00000, 0x00000000fff00000, 0x00000000fff00000) object space 19456K, 55% used [0x00000000fec00000,0x00000000ff695348,0x00000000fff00000) PSPermGen total 21504K, used 2442K [0x00000000f9a00000, 0x00000000faf00000, 0x00000000fec00000) object space 21504K, 11% used [0x00000000f9a00000,0x00000000f9c628d8,0x00000000faf00000)
1
2
3
4
5
6
7
8
9
10
D : \ > java - Xmx20m - Xms20m - Xmn1m - XX : + PrintGCDetails JVMXmn1
Heap
PSYoungGen       total 512K , used 0K [ 0x00000000fff00000 , 0x0000000100000000 , 0x0000000100000000 )
   eden space 0K , - 2147483648 % used [ 0x00000000fff00000 , 0x00000000fff00000 , 0x00000000fff00000 )
   from space 512K , 0 % used [ 0x00000000fff80000 , 0x00000000fff80000 , 0x0000000100000000 )
   to    space 512K , 0 % used [ 0x00000000fff00000 , 0x00000000fff00000 , 0x00000000fff80000 )
ParOldGen       total 19456K , used 10836K [ 0x00000000fec00000 , 0x00000000fff00000 , 0x00000000fff00000 )
   object space 19456K , 55 % used [ 0x00000000fec00000 , 0x00000000ff695348 , 0x00000000fff00000 )
PSPermGen       total 21504K , used 2442K [ 0x00000000f9a00000 , 0x00000000faf00000 , 0x00000000fec00000 )
   object space 21504K , 11 % used [ 0x00000000f9a00000 , 0x00000000f9c628d8 , 0x00000000faf00000 )

下面按15m的新生代設置,所有分配在eden區,老年代沒有使用,沒有觸發gc。 spa

D:\>java -Xmx20m -Xms20m -Xmn15m -XX:+PrintGCDetails JVMXmn1 Heap PSYoungGen total 13824K, used 11525K [0x00000000ff100000, 0x0000000100000000, 0x0000000100000000) eden space 12288K, 93% used [0x00000000ff100000,0x00000000ffc417c8,0x00000000ffd00000) from space 1536K, 0% used [0x00000000ffe80000,0x00000000ffe80000,0x0000000100000000) to space 1536K, 0% used [0x00000000ffd00000,0x00000000ffd00000,0x00000000ffe80000) ParOldGen total 5120K, used 0K [0x00000000fea00000, 0x00000000fef00000, 0x00000000ff100000) object space 5120K, 0% used [0x00000000fea00000,0x00000000fea00000,0x00000000fef00000) PSPermGen total 21504K, used 2442K [0x00000000f9800000, 0x00000000fad00000, 0x00000000fea00000) object space 21504K, 11% used [0x00000000f9800000,0x00000000f9a628d8,0x00000000fad00000)
1
2
3
4
5
6
7
8
9
10
D : \ > java - Xmx20m - Xms20m - Xmn15m - XX : + PrintGCDetails JVMXmn1
Heap
PSYoungGen       total 13824K , used 11525K [ 0x00000000ff100000 , 0x0000000100000000 , 0x0000000100000000 )
   eden space 12288K , 93 % used [ 0x00000000ff100000 , 0x00000000ffc417c8 , 0x00000000ffd00000 )
   from space 1536K , 0 % used [ 0x00000000ffe80000 , 0x00000000ffe80000 , 0x0000000100000000 )
   to    space 1536K , 0 % used [ 0x00000000ffd00000 , 0x00000000ffd00000 , 0x00000000ffe80000 )
ParOldGen       total 5120K , used 0K [ 0x00000000fea00000 , 0x00000000fef00000 , 0x00000000ff100000 )
   object space 5120K , 0 % used [ 0x00000000fea00000 , 0x00000000fea00000 , 0x00000000fef00000 )
PSPermGen       total 21504K , used 2442K [ 0x00000000f9800000 , 0x00000000fad00000 , 0x00000000fea00000 )
   object space 21504K , 11 % used [ 0x00000000f9800000 , 0x00000000f9a628d8 , 0x00000000fad00000 )

下面按8m的新生代設置,觸發了一次gc,因爲from和to的大小小於1M的對象大小,eden區會直接進入老年代。 線程

D:\>java -Xmx20m -Xms20m -Xmn8m -XX:+PrintGCDetails JVMXmn1 [GC [PSYoungGen: 5954K->536K(7168K)] 5954K->1560K(19456K), 0.0021655 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap PSYoungGen total 7168K, used 5971K [0x00000000ff800000, 0x0000000100000000, 0x0000000100000000) eden space 6144K, 88% used [0x00000000ff800000,0x00000000ffd4ecb8,0x00000000ffe00000) from space 1024K, 52% used [0x00000000ffe00000,0x00000000ffe86010,0x00000000fff00000) to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000) ParOldGen total 12288K, used 1024K [0x00000000fec00000, 0x00000000ff800000, 0x00000000ff800000) object space 12288K, 8% used [0x00000000fec00000,0x00000000fed00010,0x00000000ff800000) PSPermGen total 21504K, used 2445K [0x00000000f9a00000, 0x00000000faf00000, 0x00000000fec00000) object space 21504K, 11% used [0x00000000f9a00000,0x00000000f9c63400,0x00000000faf00000)
1
2
3
4
5
6
7
8
9
10
11
D : \ > java - Xmx20m - Xms20m - Xmn8m - XX : + PrintGCDetails JVMXmn1
[ GC [ PSYoungGen : 5954K -> 536K ( 7168K ) ] 5954K -> 1560K ( 19456K ) , 0.0021655 secs ] [ Times : user = 0.00 sys = 0.00 , real = 0.00 secs ]
Heap
PSYoungGen       total 7168K , used 5971K [ 0x00000000ff800000 , 0x0000000100000000 , 0x0000000100000000 )
   eden space 6144K , 88 % used [ 0x00000000ff800000 , 0x00000000ffd4ecb8 , 0x00000000ffe00000 )
   from space 1024K , 52 % used [ 0x00000000ffe00000 , 0x00000000ffe86010 , 0x00000000fff00000 )
   to    space 1024K , 0 % used [ 0x00000000fff00000 , 0x00000000fff00000 , 0x0000000100000000 )
ParOldGen       total 12288K , used 1024K [ 0x00000000fec00000 , 0x00000000ff800000 , 0x00000000ff800000 )
   object space 12288K , 8 % used [ 0x00000000fec00000 , 0x00000000fed00010 , 0x00000000ff800000 )
PSPermGen       total 21504K , used 2445K [ 0x00000000f9a00000 , 0x00000000faf00000 , 0x00000000fec00000 )
   object space 21504K , 11 % used [ 0x00000000f9a00000 , 0x00000000f9c63400 , 0x00000000faf00000 )

下面按7m的新生代設置,from和to的大小能夠爲1/xmn,大於觸發了3次新生代gc,一共回收了7M左右的空間,最後剩餘3M在系統當中,沒有使用老年代。 debug

D:\>java -Xmx20m -Xms20m -Xmn7m -XX:SurvivorRatio=2 -XX:+PrintGCDetails JVMXmn1 [GC [PSYoungGen: 3785K->1512K(5632K)] 3785K->1568K(18944K), 0.0024118 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC [PSYoungGen: 4755K->1528K(5632K)] 4811K->1584K(18944K), 0.0013799 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC [PSYoungGen: 4631K->1496K(5632K)] 4687K->1552K(18944K), 0.0010990 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap PSYoungGen total 5632K, used 2561K [0x00000000ff900000, 0x0000000100000000, 0x0000000100000000) eden space 4096K, 26% used [0x00000000ff900000,0x00000000ffa0a448,0x00000000ffd00000) from space 1536K, 97% used [0x00000000ffd00000,0x00000000ffe76020,0x00000000ffe80000) to space 1536K, 0% used [0x00000000ffe80000,0x00000000ffe80000,0x0000000100000000) ParOldGen total 13312K, used 56K [0x00000000fec00000, 0x00000000ff900000, 0x00000000ff900000) object space 13312K, 0% used [0x00000000fec00000,0x00000000fec0e000,0x00000000ff900000) PSPermGen total 21504K, used 2445K [0x00000000f9a00000, 0x00000000faf00000, 0x00000000fec00000) object space 21504K, 11% used [0x00000000f9a00000,0x00000000f9c63400,0x00000000faf00000)
1
2
3
4
5
6
7
8
9
10
11
12
13
D : \ > java - Xmx20m - Xms20m - Xmn7m - XX : SurvivorRatio = 2 - XX : + PrintGCDetails JVMXmn1
[ GC [ PSYoungGen : 3785K -> 1512K ( 5632K ) ] 3785K -> 1568K ( 18944K ) , 0.0024118 secs ] [ Times : user = 0.00 sys = 0.00 , real = 0.00 secs ]
[ GC [ PSYoungGen : 4755K -> 1528K ( 5632K ) ] 4811K -> 1584K ( 18944K ) , 0.0013799 secs ] [ Times : user = 0.00 sys = 0.00 , real = 0.00 secs ]
[ GC [ PSYoungGen : 4631K -> 1496K ( 5632K ) ] 4687K -> 1552K ( 18944K ) , 0.0010990 secs ] [ Times : user = 0.00 sys = 0.00 , real = 0.00 secs ]
Heap
PSYoungGen       total 5632K , used 2561K [ 0x00000000ff900000 , 0x0000000100000000 , 0x0000000100000000 )
   eden space 4096K , 26 % used [ 0x00000000ff900000 , 0x00000000ffa0a448 , 0x00000000ffd00000 )
   from space 1536K , 97 % used [ 0x00000000ffd00000 , 0x00000000ffe76020 , 0x00000000ffe80000 )
   to    space 1536K , 0 % used [ 0x00000000ffe80000 , 0x00000000ffe80000 , 0x0000000100000000 )
ParOldGen       total 13312K , used 56K [ 0x00000000fec00000 , 0x00000000ff900000 , 0x00000000ff900000 )
   object space 13312K , 0 % used [ 0x00000000fec00000 , 0x00000000fec0e000 , 0x00000000ff900000 )
PSPermGen       total 21504K , used 2445K [ 0x00000000f9a00000 , 0x00000000faf00000 , 0x00000000fec00000 )
   object space 21504K , 11 % used [ 0x00000000f9a00000 , 0x00000000f9c63400 , 0x00000000faf00000 )

新生代佔一半大小(10m),倖存區爲3:1:1(6m:2m,2m),觸發了1次gc,回收了7m左右空間,沒有使用老年代。對於這種臨時對象,減小老年代的使用是gc優化的關鍵。

D:\>java -Xmx20m -Xms20m -XX:NewRatio=1 -XX:SurvivorRatio=3 -XX:+PrintGCDetails JVMXmn1 [GC [PSYoungGen: 5954K->1624K(8192K)] 5954K->1624K(18432K), 0.0023152 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Heap PSYoungGen total 8192K, used 7059K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000) eden space 6144K, 88% used [0x00000000ff600000,0x00000000ffb4ecb8,0x00000000ffc00000) from space 2048K, 79% used [0x00000000ffc00000,0x00000000ffd96020,0x00000000ffe00000) to space 2048K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x0000000100000000) ParOldGen total 10240K, used 0K [0x00000000fec00000, 0x00000000ff600000,0x00000000ff600000) object space 10240K, 0% used [0x00000000fec00000,0x00000000fec00000,0x00000000ff600000) PSPermGen total 21504K, used 2445K [0x00000000f9a00000, 0x00000000faf00000, 0x00000000fec00000) object space 21504K, 11% used [0x00000000f9a00000,0x00000000f9c63400,0x00000000faf00000)
1
2
3
4
5
6
7
8
9
10
11
D : \ > java - Xmx20m - Xms20m - XX : NewRatio = 1 - XX : SurvivorRatio = 3 - XX : + PrintGCDetails JVMXmn1
[ GC [ PSYoungGen : 5954K -> 1624K ( 8192K ) ] 5954K -> 1624K ( 18432K ) , 0.0023152 secs ] [ Times : user = 0.00 sys = 0.00 , real = 0.00 secs ]
Heap
PSYoungGen       total 8192K , used 7059K [ 0x00000000ff600000 , 0x0000000100000000 , 0x0000000100000000 )
   eden space 6144K , 88 % used [ 0x00000000ff600000 , 0x00000000ffb4ecb8 , 0x00000000ffc00000 )
   from space 2048K , 79 % used [ 0x00000000ffc00000 , 0x00000000ffd96020 , 0x00000000ffe00000 )
   to    space 2048K , 0 % used [ 0x00000000ffe00000 , 0x00000000ffe00000 , 0x0000000100000000 )
ParOldGen       total 10240K , used 0K [ 0x00000000fec00000 , 0x00000000ff600000 , 0x00000000ff600000 )
   object space 10240K , 0 % used [ 0x00000000fec00000 , 0x00000000fec00000 , 0x00000000ff600000 )
PSPermGen       total 21504K , used 2445K [ 0x00000000f9a00000 , 0x00000000faf00000 , 0x00000000fec00000 )
   object space 21504K , 11 % used [ 0x00000000f9a00000 , 0x00000000f9c63400 , 0x00000000faf00000 )

^^

相關文章
相關標籤/搜索