一、堆參數設置
-xx:+printgc 使用這個參數,虛擬機啟動后,只要遇到gc就會打印日志
-xx:+useserialgc 配置串行回收器
-xx:+printgcdetails 可以查看詳細信息,包括各個區的情況
-xms:設置java程序啟動時初始化堆大小
-xmx:設置java程序能獲得最大的堆大小
-xmx20m -xms5m -xx:+printcommandlineflags:可以將隱式或者顯示傳給虛擬機的參數輸出
在實際工作中,我們可以直接將初始的堆大小與最大堆大小設置相等,這樣的好處是可以減少程序運行時的垃圾回收次數,從而提高性能。
配置運行時參數:-xx:+printgc -xms5m -xmx20m -xx:+useserialgc -xx:+printgcdetails -xx:+printcommandlineflags
運行一下demo:
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
|
package com.ietree.basicskill.jvm; public class demo01 { public static void main(string[] args) { // -xx:+printgc -xms5m -xmx20m -xx:+useserialgc -xx:+printgcdetails -xx:+printcommandlineflags //查看gc信息 system.out.println( "max memory:" + runtime.getruntime().maxmemory()); system.out.println( "free memory:" + runtime.getruntime().freememory()); system.out.println( "total memory:" + runtime.getruntime().totalmemory()); byte [] b1 = new byte [ 1 * 1024 * 1024 ]; system.out.println( "分配了1m" ); system.out.println( "max memory:" + runtime.getruntime().maxmemory()); system.out.println( "free memory:" + runtime.getruntime().freememory()); system.out.println( "total memory:" + runtime.getruntime().totalmemory()); byte [] b2 = new byte [ 4 * 1024 * 1024 ]; system.out.println( "分配了4m" ); system.out.println( "max memory:" + runtime.getruntime().maxmemory()); system.out.println( "free memory:" + runtime.getruntime().freememory()); system.out.println( "total memory:" + runtime.getruntime().totalmemory()); } } |
程序輸出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
-xx:initialheapsize= 5242880 -xx:maxheapsize= 20971520 -xx:+printcommandlineflags -xx:+printgc -xx:+printgcdetails -xx:+usecompressedclasspointers -xx:+usecompressedoops -xx:-uselargepagesindividualallocation -xx:+useserialgc max memory: 20316160 free memory: 5286032 total memory: 6094848 [gc (allocation failure) [defnew: 789k->191k(1856k), 0.0026441 secs] 789k->530k(5952k), 0.0027627 secs] [times: user= 0.00 sys= 0.00 , real= 0.00 secs] 分配了1m max memory: 20316160 free memory: 4469352 total memory: 6094848 [gc (allocation failure) [defnew: 1249k->0k(1856k), 0.0022285 secs][tenured: 1554k->1554k(4096k), 0.0031394 secs] 1587k->1554k(5952k), [metaspace: 2597k->2597k(1056768k)], 0.0054980 secs] [times: user= 0.00 sys= 0.00 , real= 0.01 secs] 分配了4m max memory: 20316160 free memory: 4538184 total memory: 10358784 heap def new generation total 1920k, used 68k [ 0x00000000fec00000 , 0x00000000fee10000 , 0x00000000ff2a0000 ) eden space 1728k, 3 % used [ 0x00000000fec00000 , 0x00000000fec113e0 , 0x00000000fedb0000 ) from space 192k, 0 % used [ 0x00000000fedb0000 , 0x00000000fedb0000 , 0x00000000fede0000 ) to space 192k, 0 % used [ 0x00000000fede0000 , 0x00000000fede0000 , 0x00000000fee10000 ) tenured generation total 8196k, used 5650k [ 0x00000000ff2a0000 , 0x00000000ffaa1000 , 0x0000000100000000 ) the space 8196k, 68 % used [ 0x00000000ff2a0000 , 0x00000000ff824888 , 0x00000000ff824a00 , 0x00000000ffaa1000 ) metaspace used 2603k, capacity 4486k, committed 4864k, reserved 1056768k class space used 288k, capacity 386k, committed 512k, reserved 1048576k |
在此程序輸出的結果中,可以看到堆的詳細信息,比如可以看到它的新生代信息、老年代信息、永久區信息等。
二、新生代參數配置
-xmn:可以設置新生代的大小,設置一個比較大的新生代會減少老年代的大小,這個參數對系統性能以及gc行為有很大的影響,新生代大小一般會設置整個堆空間的1/3到1/4左右。
-xx:survivorratio:用來設置新生代中eden空間和from/to空間的比例。含義:-xx:survivorratio=eden/from=eden/to。
不同的堆分布情況,對系統執行會產生一定的影響,在實際工作中,應該根據系統的特點做出合理的配置,基本策略:盡可能將對象預留在新生代,減少老年代的gc次數。
除了可以設置新生代的絕對大小(-xmn),還可以使用(-xx:newratio)設置新生代和老年代的比例:-xx:newratio=老年代/新生代。
配置運行時參數:
-xms20m -xmx20m -xmn1m -xx:survivorratio=2 -xx:+printgcdetails
-xx:+useserialgc
運行demo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.ietree.basicskill.jvm; public class demo2 { public static void main(string[] args) { // 第一次配置(eden 2 = from 1 + to 1) // -xms20m -xmx20m -xmn1m -xx:survivorratio=2 -xx:+printgcdetails -xx:+useserialgc // 第二次配置 // -xms20m -xmx20m -xmn7m -xx:survivorratio=2 -xx:+printgcdetails -xx:+useserialgc // 第三次配置 // -xx:newratio=老年代/新生代 // -xms20m -xmx20m -xx:newratio=2 -xx:+printgcdetails -xx:+useserialgc byte [] b = null ; // 連續向系統申請10mb空間 for ( int i = 0 ; i < 10 ; i++) { b = new byte [ 1 * 1024 * 1024 ]; } } } |
程序運行結果:
1
2
3
4
5
6
7
8
9
10
|
[gc (allocation failure) [defnew: 508k->256k(768k), 0.0012770 secs] 508k->435k(20224k), 0.0013333 secs] [times: user= 0.00 sys= 0.00 , real= 0.00 secs] heap def new generation total 768k, used 498k [ 0x00000000fec00000 , 0x00000000fed00000 , 0x00000000fed00000 ) eden space 512k, 47 % used [ 0x00000000fec00000 , 0x00000000fec3c988 , 0x00000000fec80000 ) from space 256k, 100 % used [ 0x00000000fecc0000 , 0x00000000fed00000 , 0x00000000fed00000 ) to space 256k, 0 % used [ 0x00000000fec80000 , 0x00000000fec80000 , 0x00000000fecc0000 ) tenured generation total 19456k, used 10419k [ 0x00000000fed00000 , 0x0000000100000000 , 0x0000000100000000 ) the space 19456k, 53 % used [ 0x00000000fed00000 , 0x00000000ff72cf20 , 0x00000000ff72d000 , 0x0000000100000000 ) metaspace used 2601k, capacity 4486k, committed 4864k, reserved 1056768k class space used 288k, capacity 386k, committed 512k, reserved 1048576k |
可以看到,在新生代種,eden區域內存是from和to區域內存的2倍。即-xx:survivorratio=2參數起了作用。
配置運行參數:-xms20m -xmx20m -xx:newratio=2 -xx:+printgcdetails -xx:+useserialgc
運行以上demo可以得到一下輸出:
1
2
3
4
5
6
7
8
9
10
11
|
[gc (allocation failure) [defnew: 4979k->529k(6144k), 0.0028804 secs] 4979k->1553k(19840k), 0.0029572 secs] [times: user= 0.00 sys= 0.00 , real= 0.00 secs] [gc (allocation failure) [defnew: 5756k->0k(6144k), 0.0021035 secs] 6780k->2576k(19840k), 0.0021487 secs] [times: user= 0.00 sys= 0.00 , real= 0.00 secs] heap def new generation total 6144k, used 1134k [ 0x00000000fec00000 , 0x00000000ff2a0000 , 0x00000000ff2a0000 ) eden space 5504k, 20 % used [ 0x00000000fec00000 , 0x00000000fed1b9d8 , 0x00000000ff160000 ) from space 640k, 0 % used [ 0x00000000ff160000 , 0x00000000ff160000 , 0x00000000ff200000 ) to space 640k, 0 % used [ 0x00000000ff200000 , 0x00000000ff200000 , 0x00000000ff2a0000 ) tenured generation total 13696k, used 2576k [ 0x00000000ff2a0000 , 0x0000000100000000 , 0x0000000100000000 ) the space 13696k, 18 % used [ 0x00000000ff2a0000 , 0x00000000ff524140 , 0x00000000ff524200 , 0x0000000100000000 ) metaspace used 2601k, capacity 4486k, committed 4864k, reserved 1056768k class space used 288k, capacity 386k, committed 512k, reserved 1048576k |
發現tenured generation老年代的內存是new generation 新生代內存的2倍。
三、堆溢出參數配置
在java程序的運行過程中,如果對空間不足,則會拋出內存溢出的錯誤(out of memory)oom,一旦這類問題發生在生產環境,則可能引起嚴重的業務中斷,java虛擬機提供了-xx:+heapdumponoutofmemoryerror,
使用該參數可以在內存溢出時導出整個堆信息,與之配合使用的還有參數-xx:heapdumppath,可以設置導出堆的存放路徑。
內存分析工具:memory analyzer
配置運行時參數-xms1m -xmx1m -xx:+heapdumponoutofmemoryerror -xx:heapdumppath=d:/demo3.dump
運行demo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package com.ietree.basicskill.jvm; import java.util.vector; public class demo3 { public static void main(string[] args) { // -xms1m -xmx1m -xx:+heapdumponoutofmemoryerror -xx:heapdumppath=d:/demo3.dump // 堆內存溢出 vector v = new vector(); for ( int i = 0 ; i < 5 ; i++) { v.add( new byte [ 1 * 1024 * 1024 ]); } } } |
程序輸出的結果:
1
2
3
4
5
|
java.lang.outofmemoryerror: java heap space dumping heap to d:/demo3.dump ... heap dump file created [ 1219372 bytes in 0.009 secs] exception in thread "main" java.lang.outofmemoryerror: java heap space at com.ietree.basicskill.jvm.demo3.main(demo3.java: 11 ) |
在d:/demo3.dump可以找到對應的文件,使用內存分析工具(memory analyzer)打開:
如圖:
四、棧參數配置
java虛擬機提供了參數-xss來指定線程的最大棧空間,整個參數也直接決定了函數可調用的最大深度。
配置運行時參數:-xss1m
運行demo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.ietree.basicskill.jvm; public class demo4 { // -xss1m // -xss5m // 棧調用深度 private static int count; public static void recursion() { count++; recursion(); } public static void main(string[] args) { try { recursion(); } catch (throwable t) { system.out.println( "調用最大深入:" + count); t.printstacktrace(); } } } |
程序輸出:
1
2
3
4
5
6
7
8
9
10
11
|
調用最大深入: 20557 java.lang.stackoverflowerror at com.ietree.basicskill.jvm.demo4.recursion(demo4.java: 12 ) at com.ietree.basicskill.jvm.demo4.recursion(demo4.java: 12 ) at com.ietree.basicskill.jvm.demo4.recursion(demo4.java: 12 ) at com.ietree.basicskill.jvm.demo4.recursion(demo4.java: 12 ) at com.ietree.basicskill.jvm.demo4.recursion(demo4.java: 12 ) at com.ietree.basicskill.jvm.demo4.recursion(demo4.java: 12 ) at com.ietree.basicskill.jvm.demo4.recursion(demo4.java: 12 ) at com.ietree.basicskill.jvm.demo4.recursion(demo4.java: 12 ) ...... |
五、方法區參數配置
和java堆一樣,方法區是一塊所有線程共享的內存區域,它用于保存系統的類信息,方法區(永久區)可以保存多少信息可以對其進行配置,在默認情況下,-xx:maxpermsize為64m,
如果系統運行時生產大量的類,就需要設置一個相對合適的方法區,以免出現永久區內存溢出的問題。
-xx:permsize=64m -xx:maxpermsize=64m
六、直接內存參數配置
直接內存也是java程序中非常重要的組成部分,特別是廣泛用在nio中,直接內存跳過了java堆,使用java程序可以直接訪問原生堆空間,因此在一定程度上加快了內存空間的訪問速度。
但是說直接內存一定就可以提高內存訪問速度也不見得,具體情況具體分析。
相關配置參數:-xx:maxdirectmemorysize,如果不設置,默認值為最大堆空間,即-xmx。直接內存使用達到上限時,就會觸發垃圾回收,如果不能有效的釋放空間,就會引起系統的oom。
七、對象進入老年代的參數配置
一般而言,對象首次創建會被放置在新生代的eden區,如果沒有gc介入,則對象不會離開eden區,那么eden區的對象如何進入老年代呢?
通常情況下,只要對象的年齡達到一定的大小,就會自動離開年輕代進入老年代,對象年齡是由對象經歷數次gc決定的,在新生代每次gc之后如果對象沒有被回收,則年齡加1。
虛擬機提供了一個參數來控制新生代對象的最大年齡,當超過這個年齡范圍就會晉升老年代。
-xx:maxtenuringthreshold,默認情況下為15
配置運行時參數:-xmx64m -xms64m -xx:+printgcdetails
運行demo:
1
2
3
4
5
6
7
8
9
10
11
12
|
package com.ietree.basicskill.jvm; public class demo5 { public static void main(string[] args) { // 初始的對象在eden區 // 參數:-xmx64m -xms64m -xx:+printgcdetails for ( int i = 0 ; i < 5 ; i++) { byte [] b = new byte [ 1024 * 1024 ]; } } } |
程序輸出:
1
2
3
4
5
6
7
8
9
|
heap psyounggen total 18944k, used 6759k [ 0x00000000feb00000 , 0x0000000100000000 , 0x0000000100000000 ) eden space 16384k, 41 % used [ 0x00000000feb00000 , 0x00000000ff199db8 , 0x00000000ffb00000 ) from space 2560k, 0 % used [ 0x00000000ffd80000 , 0x00000000ffd80000 , 0x0000000100000000 ) to space 2560k, 0 % used [ 0x00000000ffb00000 , 0x00000000ffb00000 , 0x00000000ffd80000 ) paroldgen total 44032k, used 0k [ 0x00000000fc000000 , 0x00000000feb00000 , 0x00000000feb00000 ) object space 44032k, 0 % used [ 0x00000000fc000000 , 0x00000000fc000000 , 0x00000000feb00000 ) metaspace used 2601k, capacity 4486k, committed 4864k, reserved 1056768k class space used 288k, capacity 386k, committed 512k, reserved 1048576k |
結論:對象首次創建會被放置在新生代的eden區,因此輸出結果中from和to區都為0%。
根據設置maxtenuringthreshold參數,可以指定新生代對象經過多少次回收后進入老年代。另外,大對象新生代eden區無法裝入時,也會直接進入老年代。
jvm里有個參數可以設置對象的大小超過在指定的大小之后,直接晉升老年代。
-xx:pretenuresizethreshold=15
參數:-xmx1024m -xms1024m -xx:+useserialgc -xx:maxtenuringthreshold=15 -xx:+printgcdetails
使用pretenuresizethreshold可以進行指定進入老年代的對象大小,但是要注意tlab區域優先分配空間。虛擬機對于體積不大的對象 會優先把數據分配到tlab區域中,因此就失去了在老年代分配的機會.
參數:-xmx30m -xms30m -xx:+useserialgc -xx:+printgcdetails -xx:pretenuresizethreshold=1000 -xx:-usetlab
八、tlab參數配置
tlab全稱是thread local allocation buffer即線程本地分配緩存,從名字上看是一個線程專用的內存分配區域,是為了加速對象分配對象而生的。
每一個線程都會產生一個tlab,該線程獨享的工作區域,java虛擬機使用這種tlab區來避免多線程沖突問題,提高了對象分配的效率。
tlab空間一般不會太大,當大對象無法在tlab分配時,則會直接分配到堆上。
-xx:+usetlab使用tlab
-xx:+tlabsize設置tlab大小
-xx:tlabrefillwastefraction設置維護進入tlab空間的單個對象大小,它是一個比例值,默認為64,即如果對象大于整個空間的1/64,則在堆創建對象。
-xx:+printtlab查看tlab信息
-xx:resizetlab自調整tlabrefillwastefraction閾值。
參數:-xx:+usetlab -xx:+printtlab -xx:+printgc -xx:tlabsize=102400 -xx:-resizetlab -xx:tlabrefillwastefraction=100 -xx:-doescapeanalysis -server
以上這篇jvm之參數分配(全面講解)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。