jstat怎麼看內存配置
A. 如何查看Jstat的參數結果和分析內存使用,請大牛指點
jmap傾向於分析jvm內存中對象冊皮信息的話腔衡...可查看jsat幫州圓差助信息,我經常用-gcutil,這個參數的...環境,使用什麼樣的工具是無所謂的,
B. jvm 性能調優工具之 jstat 命令詳解
Jstat名稱:java Virtual Machine statistics monitoring tool
功能描述:
Jstat是JDK自帶的一個輕量級小工具。它位於java的bin目錄下,主要利用JVM內建的指令對Java應用程序的資源和性能進行實時的命令行的監控,包括了對Heap size和垃圾回收狀況的監控。
命令用法:jstat [-命令選項] [vmid] [間隔時間/毫秒] [查詢次數]
注意:使用的jdk版本是jdk8。
C:\Users\Administrator>jstat -helpUsage: jstat -help|-options jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]] Definitions: <option> An option reported by the -options option <vmid> Virtual Machine Identifier. A vmid takes the following form: <lvmid>[@<hostname>[:<port>]] Where <lvmid> is the local vm identifier for the target Java virtual machine, typically a process id; <hostname> is the name of the host running the target Java virtual machine; and <port> is the port number for the rmiregistry on the target host. See the jvmstat documentation for a more complete description of the Virtual Machine Identifier. <lines> Number of samples between header lines. <interval> Sampling interval. The following forms are allowed: <n>["ms"|"s"] Where <n> is an integer and the suffix specifies the units as milliseconds("ms") or seconds("s"). The default units are "ms". <count> Number of samples to take before terminating. -J<flag> Pass <flag> directly to the runtime system.
option:參數選項
-t:可以在列印的列加上Timestamp列,用於顯示系統運行的時間
-h:可以在周期性數據輸出的時型蠢候,指定輸出多少行以後輸出一次表頭
vmid:Virtual Machine ID( 進程的 pid)
interval:執行每次的間隔時間,單位為毫秒
count:用於指定輸出多少次記錄,預設則會一直列印
option 可以從下面參數中選擇
jstat -options
-class 用卜悄陪於查看類載入情況的統計
-compiler 用於查看HotSpot中即時編譯器編譯情運檔況的統計
-gc 用於查看JVM中堆的垃圾收集情況的統計
-gccapacity 用於查看新生代、老生代及持久代的存儲容量情況
-gcmetacapacity 顯示metaspace的大小
-gcnew 用於查看新生代垃圾收集的情況
-gcnewcapacity 用於查看新生代存儲容量的情況
-gcold 用於查看老生代及持久代垃圾收集的情況
-gcoldcapacity 用於查看老生代的容量
-gcutil 顯示垃圾收集信息
-gccause 顯示垃圾回收的相關信息(通-gcutil),同時顯示最後一次僅當前正在發生的垃圾收集的原因
-printcompilation 輸出JIT編譯的方法信息
示例:
1.-class 類載入統計
[root@hadoop ~]# jps #先通過jps獲取到java進程號(這里是一個zookeeper進程)3346 QuorumPeerMain7063 Jps[root@hadoop ~]# jstat -class 3346 #統計JVM中載入的類的數量與sizeLoaded Bytes Unloaded Bytes Time 1527 2842.7 0 0.0 1.02
Loaded:載入類的數量
Bytes:載入類的size,單位為Byte
Unloaded:卸載類的數目
Bytes:卸載類的size,單位為Byte
Time:載入與卸載類花費的時間
2.-compiler 編譯統計
[root@hadoop ~]# jstat -compiler 3346 #用於查看HotSpot中即時編譯器編譯情況的統計Compiled Failed Invalid Time FailedType FailedMethod 404 0 0 0.19 0
Compiled:編譯任務執行數量
Failed:編譯任務執行失敗數量
Invalid:編譯任務執行失效數量
Time:編譯任務消耗時間
FailedType:最後一個編譯失敗任務的類型
FailedMethod:最後一個編譯失敗任務所在的類及方法
3.-gc 垃圾回收統計
[root@hadoop ~]# jstat -gc 3346 #用於查看JVM中堆的垃圾收集情況的統計 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 128.0 128.0 0.0 128.0 1024.0 919.8 15104.0 2042.4 8448.0 8130.4 1024.0 996.0 7 0.019 0 0.000 0.019
S0C:年輕代中第一個survivor(倖存區)的容量 (位元組)
S1C:年輕代中第二個survivor(倖存區)的容量 (位元組)
S0U:年輕代中第一個survivor(倖存區)目前已使用空間 (位元組)
S1U:年輕代中第二個survivor(倖存區)目前已使用空間 (位元組)
EC:年輕代中Eden(伊甸園)的容量 (位元組)
EU:年輕代中Eden(伊甸園)目前已使用空間 (位元組)
OC:Old代的容量 (位元組)
OU:Old代目前已使用空間 (位元組)
MC:metaspace(元空間)的容量 (位元組)
MU:metaspace(元空間)目前已使用空間 (位元組)
CCSC:當前壓縮類空間的容量 (位元組)
CCSU:當前壓縮類空間目前已使用空間 (位元組)
YGC:從應用程序啟動到采樣時年輕代中gc次數
YGCT:從應用程序啟動到采樣時年輕代中gc所用時間(s)
FGC:從應用程序啟動到采樣時old代(全gc)gc次數
FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)
GCT:從應用程序啟動到采樣時gc用的總時間(s)
4.-gccapacity 堆內存統計
[root@hadoop ~]# jstat -gccapacity 3346 #用於查看新生代、老生代及持久代的存儲容量情況 NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0[root@hadoop ~]# jstat -gccapacity -h5 3346 1000 #-h5:每5行顯示一次表頭 1000:每1秒鍾顯示一次,單位為毫秒 NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0 NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0 1280.0 83264.0 1280.0 128.0 128.0 1024.0 15104.0 166592.0 15104.0 15104.0 0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 7 0
NGCMN:年輕代(young)中初始化(最小)的大小(位元組)
NGCMX:年輕代(young)的最大容量 (位元組)
NGC:年輕代(young)中當前的容量 (位元組)
S0C:年輕代中第一個survivor(倖存區)的容量 (位元組)
S1C:年輕代中第二個survivor(倖存區)的容量 (位元組)
EC:年輕代中Eden(伊甸園)的容量 (位元組)
OGCMN:old代中初始化(最小)的大小 (位元組)
OGCMX:old代的最大容量(位元組)
OGC:old代當前新生成的容量 (位元組)
OC:Old代的容量 (位元組)
MCMN:metaspace(元空間)中初始化(最小)的大小 (位元組)
MCMX:metaspace(元空間)的最大容量 (位元組)
MC:metaspace(元空間)當前新生成的容量 (位元組)
CCSMN:最小壓縮類空間大小
CCSMX:最大壓縮類空間大小
CCSC:當前壓縮類空間大小
YGC:從應用程序啟動到采樣時年輕代中gc次數
FGC:從應用程序啟動到采樣時old代(全gc)gc次數
5.-gcmetacapacity 元數據空間統計
[root@hadoop ~]# jstat -gcmetacapacity 3346 #顯示元數據空間的大小MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT0.0 1056768.0 8448.0 0.0 1048576.0 1024.0 8 0 0.000 0.020
MCMN:最小元數據容量
MCMX:最大元數據容量
MC:當前元數據空間大小
CCSMN:最小壓縮類空間大小
CCSMX:最大壓縮類空間大小
CCSC:當前壓縮類空間大小
YGC:從應用程序啟動到采樣時年輕代中gc次數
FGC:從應用程序啟動到采樣時old代(全gc)gc次數
FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)
GCT:從應用程序啟動到采樣時gc用的總時間(s)
6.-gcnew 新生代垃圾回收統計
[root@hadoop ~]# jstat -gcnew 3346 #用於查看新生代垃圾收集的情況S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT128.0 128.0 67.8 0.0 1 15 64.0 1024.0 362.2 8 0.020
S0C:年輕代中第一個survivor(倖存區)的容量 (位元組)
S1C:年輕代中第二個survivor(倖存區)的容量 (位元組)
S0U:年輕代中第一個survivor(倖存區)目前已使用空間 (位元組)
S1U:年輕代中第二個survivor(倖存區)目前已使用空間 (位元組)
TT:持有次數限制
MTT:最大持有次數限制
DSS:期望的倖存區大小
EC:年輕代中Eden(伊甸園)的容量 (位元組)
EU:年輕代中Eden(伊甸園)目前已使用空間 (位元組)
YGC:從應用程序啟動到采樣時年輕代中gc次數
YGCT:從應用程序啟動到采樣時年輕代中gc所用時間(s)
7.-gcnewcapacity 新生代內存統計
[root@hadoop ~]# jstat -gcnewcapacity 3346 #用於查看新生代存儲容量的情況NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC1280.0 83264.0 1280.0 8320.0 128.0 8320.0 128.0 66624.0 1024.0 8 0
NGCMN:年輕代(young)中初始化(最小)的大小(位元組)
NGCMX:年輕代(young)的最大容量 (位元組)
NGC:年輕代(young)中當前的容量 (位元組)
S0CMX:年輕代中第一個survivor(倖存區)的最大容量 (位元組)
S0C:年輕代中第一個survivor(倖存區)的容量 (位元組)
S1CMX:年輕代中第二個survivor(倖存區)的最大容量 (位元組)
S1C:年輕代中第二個survivor(倖存區)的容量 (位元組)
ECMX:年輕代中Eden(伊甸園)的最大容量 (位元組)
EC:年輕代中Eden(伊甸園)的容量 (位元組)
YGC:從應用程序啟動到采樣時年輕代中gc次數
FGC:從應用程序啟動到采樣時old代(全gc)gc次數
8.-gcold 老年代垃圾回收統計
[root@hadoop ~]# jstat -gcold 3346 #用於查看老年代及持久代垃圾收集的情況MC MU CCSC CCSU OC OU YGC FGC FGCT GCT8448.0 8227.5 1024.0 1003.7 15104.0 2102.2 8 0 0.000 0.020
MC:metaspace(元空間)的容量 (位元組)
MU:metaspace(元空間)目前已使用空間 (位元組)
CCSC:壓縮類空間大小
CCSU:壓縮類空間使用大小
OC:Old代的容量 (位元組)
OU:Old代目前已使用空間 (位元組)
YGC:從應用程序啟動到采樣時年輕代中gc次數
FGC:從應用程序啟動到采樣時old代(全gc)gc次數
FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)
GCT:從應用程序啟動到采樣時gc用的總時間(s)
9.-gcoldcapacity 老年代內存統計
[root@hadoop ~]# jstat -gcoldcapacity 3346 #用於查看老年代的容量OGCMN OGCMX OGC OC YGC FGC FGCT GCT15104.0 166592.0 15104.0 15104.0 8 0 0.000 0.020
OGCMN:old代中初始化(最小)的大小 (位元組)OGCMX:old代的最大容量(位元組)OGC:old代當前新生成的容量 (位元組)OC:Old代的容量 (位元組)YGC:從應用程序啟動到采樣時年輕代中gc次數FGC:從應用程序啟動到采樣時old代(全gc)gc次數FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)GCT:從應用程序啟動到采樣時gc用的總時間(s) 在此我向大家推薦一個架構學習交流圈。交流學習指導偽鑫:1253431195(裡面有大量的面試題及答案)裡面會分享一些資深架構師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高並發、高性能、分布式、微服務架構的原理,JVM性能優化、分布式架構等這些成為架構師必備的知識體系。還能領取免費的學習資源,目前受益良多
10.-gcutil 垃圾回收統計
[root@hadoop ~]# jstat -gcutil 3346 #顯示垃圾收集信息S0 S1 E O M CCS YGC YGCT FGC FGCT GCT52.97 0.00 42.10 13.92 97.39 98.02 8 0.020 0 0.000 0.020
S0:年輕代中第一個survivor(倖存區)已使用的占當前容量百分比
S1:年輕代中第二個survivor(倖存區)已使用的占當前容量百分比
E:年輕代中Eden(伊甸園)已使用的占當前容量百分比
O:old代已使用的占當前容量百分比
M:元數據區已使用的占當前容量百分比
CCS:壓縮類空間已使用的占當前容量百分比
YGC :從應用程序啟動到采樣時年輕代中gc次數
YGCT :從應用程序啟動到采樣時年輕代中gc所用時間(s)
FGC :從應用程序啟動到采樣時old代(全gc)gc次數
FGCT :從應用程序啟動到采樣時old代(全gc)gc所用時間(s)
GCT:從應用程序啟動到采樣時gc用的總時間(s)
11.-gccause
[root@hadoop ~]# jstat -gccause 3346 #顯示垃圾回收的相關信息(通-gcutil),同時顯示最後一次或當前正在發生的垃圾回收的誘因S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC52.97 0.00 46.09 13.92 97.39 98.02 8 0.020 0 0.000 0.020 Allocation Failure No GC
LGCC:最後一次GC原因
GCC:當前GC原因(No GC 為當前沒有執行GC)
12.-printcompilation JVM編譯方法統計
[root@hadoop ~]# jstat -printcompilation 3346 #輸出JIT編譯的方法信息Compiled Size Type Method421 60 1 sun/nio/ch/Util$2 clear
Compiled:編譯任務的數目
Size:方法生成的位元組碼的大小
Type:編譯類型
Method:類名和方法名用來標識編譯的方法。類名使用/做為一個命名空間分隔符。方法名是給定類中的方法。上述格式是由-XX:+PrintComplation選項進行設置的
遠程監控
與jps一樣,jstat也支持遠程監控,同樣也需要開啟安全授權,方法參照jps。
C:\Users\Administrator>jps 192.168.146.1283346 QuorumPeerMain3475 JstatdC:\Users\Administrator>jstat -gcutil [email protected] S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 52.97 0.00 65.15 13.92 97.39 98.02 8 0.020 0 0.000 0.020
C. java內存查看與分析
業界有很多強大的java profile的工具,比如Jporfiler,yourkit,這些收費的東西我就不想說了,想說的是,其實java自己就提供了很多內存監控的小工具,下面列舉的工具只是一小部分,仔細研究下扒陵jdk的工具,還是蠻有意思的呢:)
1:gc日誌輸出
在jvm啟動參數中加入 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimestamps -XX:+PrintGCApplicationStopedTime,jvm將會按照這些參數順序輸出gc概要信息,詳細信息,gc時間信息,gc造成的應用暫停時間。如果在剛才的參數後面加入參數 -Xloggc:文件路徑,gc信息將會輸出到指定的文件中。其他參數還有
-verbose:gc和-XX:+PrintTenuringDistribution等。
2:jconsole
jconsole是jdk自帶的一個內存分析工具,它提供了圖形界面。可以查看到被監控的jvm的內存信息,線程信息,類載入信息,MBean信息。
jconsole位於jdk目錄下的bin目錄,在windows下是jconsole.exe,在unix和linux下是jconsole.sh,jconsole可以監控本地應用,也可以監控遠程應用。 要監控本地應用,執行jconsole pid,pid就是運行的java進程id,如果不帶上pid參數,則執行jconsole命令後,會看到一個對話框彈出,上面列出了本地的java進程,可以選擇一個進行監控。如果要遠程監控,則要在遠程伺服器的jvm參數里加入一些東西,因為jconsole的遠程監控基於jmx的,關於jconsole詳細用法,請見專門介紹jconsle的文章,我也會在博客里專門詳細介紹jconsole。
3:jviusalvm
在JDK6 update 7之後,jdk推出了另外一個工具:jvisualvm,java可視化虛擬機,它不但提供了jconsole類似的功能,還提供了jvm內存和cpu實時診斷,還有手動mp出jvm內存情況,手動執行gc。
和jconsole一樣,運行jviusalvm,在jdk的bin目錄下執行jviusalvm,windows下是jviusalvm.exe,linux和unix下是jviusalvm.sh。滲此租
4:jmap
jmap是jdk自帶的jvm內存分析的工具,叢兆位於jdk的bin目錄。jdk1.6中jmap命令用法:
Usage:
jmap -histo pid
(to connect to running process and print histogram of java object heap
jmap -mp:mp-options pid
(to connect to running process and mp java heap)
mp-options:
format=b binary default
file=file mp heap to file
Example: jmap -mp:format=b,file=heap.bin pid
jmap -histo pid在屏幕上顯示出指定pid的jvm內存狀況。以我本機為例,執行該命令,屏幕顯示:
num #instances #bytes class name
----------------------------------------------
1: 24206 2791864 constMethodKlass
2: 22371 2145216 [C
3: 24206 1940648 methodKlass
4: 1951 1364496 constantPoolKlass
5: 26543 1282560 symbolKlass
6: 6377 1081744 [B
7: 1793 909688 constantPoolCacheKlass
8: 1471 614624 instanceKlassKlass
9: 14581 548336 [Ljava.lang.Object;
10: 3863 513640 [I
11: 20677 496248 java.lang.String
12: 3621 312776 [Ljava.util.HashMap$Entry;
13: 3335 266800 java.lang.reflect.Method
14: 8256 264192 java.io.ObjectStreamClass$WeakClassKey
15: 7066 226112 java.util.TreeMap$Entry
16: 2355 173304 [S
17: 1687 161952 java.lang.Class
18: 2769 150112 [[I
19: 3563 142520 java.util.HashMap
20: 5562 133488 java.util.HashMap$Entry
Total 239019 17140408
為了方便查看,我刪掉了一些行。從上面的信息很容易看出,#instance指的是對象數量,#bytes指的是這些對象佔用的內存大小,class name指的是對象類型。
再看jmap的mp選項,這個選項是將jvm的堆中內存信息輸出到一個文件中,在我本機執行
jmap -mp:file=c:mp.txt 340
注意340是我本機的java進程pid,mp出來的文件比較大有10幾M,而且我只是開了tomcat,跑了一個很簡單的應用,且沒有任何訪問,可以想像,大型繁忙的伺服器上,mp出來的文件該有多大。需要知道的是,mp出來的文件信息是很原始的,絕不適合人直接觀看,而jmap -histo顯示的內容又太簡單,例如只顯示某些類型的對象佔用多大內存,以及這些對象的數量,但是沒有更詳細的信息,例如這些對象分別是由誰創建的。那這么說,mp出來的文件有什麼用呢?當然有用,因為有專門分析jvm的內存mp文件的工具。
5:jhat
上面說了,有很多工具都能分析jvm的內存mp文件,jhat就是sun jdk6及以上版本自帶的工具,位於jdk的bin目錄,執行 jhat -J -Xmx512m [file] ,file就是mp文件路徑。jhat內置一個簡單的web伺服器,此命令執行後,jhat在命令行里顯示分析結果的訪問地址,可以用-port選項指定埠,具體用法可以執行jhat -heap查看幫助信息。訪問指定地址後,就能看到頁面上顯示的信息,比jmap -histo命令顯示的豐富得多,更為詳細。
6:eclipse內存分析器
上面說了jhat,它能分析jvm的mp文件,但是全部是文字顯示,eclipse memory analyzer,是一個eclipse提供用於分析jvm 堆mp的插件,它的分析速度比jhat快,分析結果是圖形界面顯示,比jhat的可讀性更高。其實jvisualvm也可以分析mp文件,也是有圖形界面顯示的。
7:jstat
如果說jmap傾向於分析jvm內存中對象信息的話,那麼jsta就是傾向於分析jvm內存的gc情況。都是jvm內存分析工具,但顯然,它們是從不同維度來分析的。jsat常用的參數有很多,如 -gc,-gcutil,-gccause,這些選項具體作用可查看jsat幫助信息,我經常用-gcutil,這個參數的作用不斷的顯示當前指定的jvm內存的垃圾收集的信息。
我在本機執行 jstat -gcutil 340 10000,這個命令是每個10秒鍾輸出一次jvm的gc信息,10000指的是間隔時間為10000毫秒。屏幕上顯示如下信息(我只取了第一行,因為是按的一定頻率顯示,所以實際執行的時候,會有很多行):
S0 S1 E O P YGC YGCT FGC FGCT GCT
54.62 0.00 42.87 43.52 86.24 1792 5.093 33 7.670 12.763
額怎麼說呢,要看懂這些信息代表什麼意思,還必須對jvm的gc機制有一定的了解才行啊。其實如果對sun的 hot spot jvm的gc比較了解的人,應該很容易看懂這些信息,但是不清楚gc機制的人,有點莫名其妙,所以在這里我還是先講講sun的jvm的gc機制吧。說到gc,其實不僅僅只是java的概念,其實在java之前,就有很多語言有gc的概念了,gc嘛就是垃圾收集的意思,更多的是一種演算法性的東西,而跟具體語言沒太大關系,所以關於gc的歷史,gc的主流演算法我就不講了,那扯得太遠了,扯得太遠了就是扯淡。sun現在的jvm,內存的管理模型是分代模型,所以gc當然是分代收集了。分代是什麼意思呢?就是將對象按照生命周期分成三個層次,分別是:新生代,舊生代,持久代。對象剛開始分配的時候,大部分都在新生代,當新生代gc提交被觸發後了,執行一次新生代范圍內的gc,這叫minor gc,如果執行了幾次minor gc後,還有對象存活,將這些對象轉入舊生代,因為這些對象已經經過了組織的重重考驗了哇。舊生代的gc頻率會更低一些,如果舊生代執行了gc,那就是full gc,因為不是局部gc,而是全內存范圍的gc,這會造成應用停頓,因為全內存收集,必須封鎖內存,不許有新的對象分配到內存,持久代就是一些jvm期間,基本不會消失的對象,例如class的定義,jvm方法區信息,例如靜態塊。需要主要的是,新生代里又分了三個空間:eden,susvivor0,susvivor1,按字面上來理解,就是伊甸園區,倖存1區,倖存2區。新對象分配在eden區中,eden區滿時,採用標記-復制演算法,即檢查出eden區存活 的對象,並將這些對象復制到是s0或s1中,然後清空eden區。jvm的gc說開來,不只是這么簡單,例如還有串列收集,並行收集,並發收集,還有著名的火車演算法,不過那說得太遠了,現在對這個有大致了解就好。說到這里,再來看一下上面輸出的信息:
S0 S1 E O P YGC YGCT FGC FGCT GCT
54.62 0.00 42.87 43.52 86.24 1792 5.093 33 7.670 12.763
S0:新生代的susvivor0區,空間使用率為5462%
S1:新生代的susvivor1區,空間使用率為0.00%(因為還沒有執行第二次minor收集)
E:eden區,空間使用率42.87%
O:舊生代,空間使用率43.52%
P:持久帶,空間使用率86.24%
YGC:minor gc執行次數1792次
YGCT:minor gc耗費的時間5.093毫秒
FGC:full gc執行次數33
FGCT:full gc耗費的時間7.670毫秒
GCT:gc耗費的總時間12.763毫秒
怎樣選擇工具
上面列舉的一些工具,各有利弊,其實如果在開發環境,使用什麼樣的工具是無所謂的,只要能得到結果就好。但是在生產環境里,卻不能亂選擇,因為這些工具本身就會耗費大量的系統資源,如果在一個生產伺服器壓力很大的時候,貿然執行這些工具,可能會造成很意外的情況。最好不要在伺服器本機監控,遠程監控會比較好一些,但是如果要遠程監控,伺服器端的啟動腳本要加入一些jvm參數,例如用jconsloe遠程監控tomcat或jboss等,都需要設置jvm的jmx參數,如果僅僅只是分析伺服器的內存分配和gc信息,強烈推薦,先用jmap導出伺服器端的jvm的堆mp文件,然後再用jhat,或者jvisualvm,或者eclipse內存分析器來分析內存狀況。
D. 如何查看unix 的java內存使用情況
jmap (linux下特有,也是很常用的一個命令)
觀察運行中的jvm物理內存的佔用情況。
參數如下飢豎:
-heap :列印jvm heap的情況
-histo: 列印jvm heap的直方圖。其輸出信息包括類名,對象數量,對象佔用大小。
-histo:live : 同上,但是只答應存活對象的情況
-permstat: 列印permanent generation heap情況
命令使用:
jmap -heap 3409
可以觀察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的內存使用情況
輸出內容:
jmap -histo 3409 | jmap -histo:live 3409
可以觀察heap中所有對象的情況(heap中所有生存的對象的情況)。包括對象數量和所佔空間大小。
輸出內容:
寫個腳本,可以很快把佔用heap最大的對象找出來,對付內存泄漏特別有效。
如果結果很多,可以用以下命令輸出到文本文件。
jmap -histo 3409 | jmap -histo:live 3409 > a.txt
jinfo:可以輸出並修改運行時的java 進程的opts。
jps:與unix上的ps類似,用來顯示本地的java進程,可以查看本地運行著幾個java程序,並顯示他們的進程號。
jstat:一個極強的監視VM內存工具。可以用來監視VM內存內的各種堆和非堆的大小及其內存使用量。
jmap:列印出某個java進或笑程(使用pid)內存內的所有'對象'的情況(如:產生那些對象,及其數量)。
jconsole:一個java GUI監視工具,可以以圖表化的形式顯示各種數據。並可通過遠程連接監視遠程的伺服器VM。
詳細:在使用這些工具前,先用JPS命令獲取當前的每個JVM進程號,然後選擇要查看的JVM。
jstat工具特別強大,有眾多的可選項,詳細查看堆內各個部分的使用量,以及載入類的數量。使用時,需加上查看進程的進程id,和所選參數。以下詳細介紹各個參數的意義。
jstat -class pid:顯示載入class的數量,及所佔空間等信息。
jstat -compiler pid:顯示VM實時編譯的數量等信息。
jstat -gc pid:可以顯示gc的信息,查看gc的次數,及時間。其中最後五項,分別是young gc的次數,young gc的時間,full gc的次數,full gc的時間,gc的總時間。
jstat -gccapacity:可以顯示,VM內存中三代(young,old,perm)對象的爛團大使用和佔用大小,如:PGCMN顯示的是最小perm的內存使用量,PGCMX顯示的是perm的內存最大使用量,PGC是當前新生成的perm內存佔用量,PC是但前perm內存佔用量。其他的可以根據這個類推, OC是old內純的佔用量。
jstat -gcnew pid:new對象的信息。
jstat -gcnewcapacity pid:new對象的信息及其佔用量。
jstat -gcold pid:old對象的信息。
jstat -gcoldcapacity pid:old對象的信息及其佔用量。
jstat -gcpermcapacity pid: perm對象的信息及其佔用量。
jstat -util pid:統計gc信息統計。
jstat -printcompilation pid:當前VM執行的信息。
除了以上一個參數外,還可以同時加上 兩個數字,如:jstat -printcompilation 3024 250 6是每250毫秒列印一次,一共列印6次,還可以加上-h3每三行顯示一下標題。
jmap是一個可以輸出所有內存中對象的工具,甚至可以將VM 中的heap,以二進制輸出成文本。
命令:jmap -mp:format=b,file=heap.bin
file:保存路徑及文件名
pid:進程編號
?jmap -histo:live pid| less :堆中活動的對象以及大小
?jmap -heap pid : 查看堆的使用狀況信息
jinfo:的用處比較簡單,就是能輸出並修改運行時的java進程的運行參數。用法是jinfo -opt pid 如:查看2788的MaxPerm大小可以用 jinfo -flag MaxPermSize 2788。
jconsole是一個用java寫的GUI程序,用來監控VM,並可監控遠程的VM,非常易用,而且功能非常強。使用方法:命令行里打 jconsole,選則進程就可以了。
JConsole中關於內存分區的說明。
Eden Space (heap): 內存最初從這個線程池分配給大部分對象。
Survivor Space (heap):用於保存在eden space內存池中經過垃圾回收後沒有被回收的對象。
Tenured Generation (heap):用於保持已經在 survivor space內存池中存在了一段時間的對象。
Permanent Generation (non-heap): 保存虛擬機自己的靜態(refective)數據,例如類(class)和方法(method)對象。Java虛擬機共享這些類數據。這個區域被分割為只讀的和只寫的,
Code Cache (non-heap):HotSpot Java虛擬機包括一個用於編譯和保存本地代碼(native code)的內存,叫做「代碼緩存區」(code cache)
?jstack ( 查看jvm線程運行狀態,是否有死鎖現象等等信息) : jstack pid : thread mp
?jstat -gcutil pid 1000 100 : 1000ms統計一次gc情況統計100次;
另外推薦一款查看jmap mp 的內存對象工具 MemoryAnalyzer
E. JVM內存設置
一個新上線java服務, 內存的設置該怎麼設置呢?設置成多大比較合適,既不浪費內存,又不影響性能呢?
分析:
依據的原則是根據Java Performance裡面的推薦公式來進行設置。
具體來講:
Java整個堆大小設置,Xmx 和 Xms設置為老年代存活對象的3-4倍,即FullGC之後的老年代內存佔用的3-4倍
永久代 PermSize和MaxPermSize設置為老年代存活對象的1.2-1.5倍。【永久區並不是老年代的1.2到1.5倍,而是FullGC後永久區的1.2到1.5倍 1.2x to 1.5x permanent generation space】
年輕代Xmn的設置為老年代存活對象的1-1.5倍。
老年代的內存大小設置為老年代存活對象的2-3倍。
BTW:
1、Sun官方建議年輕代的大小為整個堆的3/8左右, 所以按照上述設置的方式,基本符合Sun的建議。
2、堆大小=年輕代大小+年老代大小, 即xmx=xmn+老年代大小 。 Permsize不影響堆大小。
3、為什麼要按照上面的來進行設置呢? 沒有具體的說明,但應該是根據多種調優之後得出的一個結論。
如何確認老年代存活對象大小?
方式1 (推薦老此老/比較穩妥):
JVM參數中添加GC日誌,GC日誌中會記錄每次FullGC之後各代的內存大小,觀察老年代GC之後的空間大小。可觀察一段時間內(比如2天)的FullGC之後的內存情況,根據多次的FullGC之後的老年代的空間大小數據來預估FullGC之後老年代的存活對象大小(可根據多次FullGC之後的內存大小取平均值)
方式2: (強制觸發FullGC, 會影響線上服務,慎用)
方式1的方式比較可行,但需要更改JVM參數,並分析日誌。同時,在使用CMS回收器的時候,有可能不能觸發FullGC(只發生CMS GC),所以日誌中並沒有記錄FullGC的日誌。在分析的時候就比較難處理。
BTW:使用jstat -gcutil工具來看FullGC的時候, CMS GC是會造成2次的FullGC次數增加。 具體可參見之前寫的一篇關於jstat使用的文章
所以,有時候需要強制觸發一次FullGC,來觀察FullGC之後的老年代存活對象大小。
註:強制觸發FullGC,會造成線上服務停頓(STW),要謹慎,建議的操作方式為扒鬧,在強制FullGC前先把服務節點摘除,FullGC之後再將服務掛回可用節點,對外提供服務
在不同時間段觸發FullGC,根據多次FullGC之後的老年代內存情況來預估FullGC之後的老年代存活對象大小
如何觸發FullGC ?
使用jmap工具可觸發FullGC
jmap -mp:live,format=b,file=heap.bin <pid> 將當前的存活對象mp到文件,此時會觸發FullGC
jmap -histo:live <pid> 列印每個class的實例數目,內存佔用,類全名信息.live子參數加上後,只統計活的對象數量. 此時會觸發FullGC
具體操作實例:
以我司的一個RPC服務為例。
BTW:剛上線的新服務,不知道該設置多大的內存的時侍升候,可以先多設置一點內存,然後根據GC之後的情況來進行分析。
初始JVM內存參數設置為: Xmx=2G Xms=2G xmn=1G
使用jstat 查看當前的GC情況。如下圖:
YGC平均耗時: 173.825s/15799=11ms
FGC平均耗時:0.817s/41=19.9ms
平均大約10-20s會產生一次YGC
看起來似乎不錯,YGC觸發的頻率不高,FGC的耗時也不高,但這樣的內存設置是不是有些浪費呢?
為了快速看數據,我們使用了方式2,產生了幾次FullGC,FullGC之後,使用的jmap -heap 來看的當前的堆內存情況(也可以根據GC日誌來看)
heap情況如下圖:(命令 : jmap -heap <pid>)
上圖中的concurrent mark-sweep generation即為老年代的內存描述。
老年代的內存佔用為100M左右。 按照整個堆大小是老年代(FullGC)之後的3-4倍計算的話,設置各代的內存情況如下:
Xmx=512m Xms=512m Xmn=128m PermSize=128m 老年代的大小為 (512-128=384m)為老年代存活對象大小的3倍左右
調整之後的,heap情況
GC情況如下:
YGC 差不多在10s左右觸發一次。每次YGC平均耗時大約9.41ms。可接受。
FGC平均耗時:0.016s/2=8ms
整體的GC耗時減少。但GC頻率比之前的2G時的要多了一些。
註: 看上述GC的時候,發現YGC的次數突然會增多很多個,比如 從1359次到了1364次。具體原因是?
總結:
在內存相對緊張的情況下,可以按照上述的方式來進行內存的調優, 找到一個在GC頻率和GC耗時上都可接受的一個內存設置,可以用較小的內存滿足當前的服務需要
但當內存相對寬裕的時候,可以相對給服務多增加一點內存,可以減少GC的頻率,GC的耗時相應會增加一些。 一般要求低延時的可以考慮多設置一點內存, 對延時要求不高的,可以按照上述方式設置較小內存。
補充:
永久代(方法區)並不在堆內,所以之前有看過一篇文章中描述的 整個堆大小=年輕代+年老代+永久代的描述是不正確的。
jmap -heap pid 結果參數詳解
F. ElasticSearch性能優化實踐(JVM調優+ES調優)
近一年內對公司的 ELK 日誌系統做過性能優化,也對 SkyWalking 使用的 ES 存儲進行過性能優化,在此做一些總結。本篇主要是講 ES 在 ELK 架構中作為日誌存儲時的性能優化方案。
隨著接入ELK的應用越來越多, 每日新增索引約 230 個,新增 document 約 3000萬到 5000萬 。
每日上午和下午是日誌上傳高峰期,在 Kibana 上查看日誌,發現問題:
(1) 日誌會有 5-40 分鍾的延遲
(2) 有很多日誌丟失,無法查到
數據先是存放在 ES 的內存 buffer,然後執行 refresh 操作寫入到操作系統的內存緩存 os cache,此後數據就可以被搜索到。
所以,日誌延遲可能是我們的數據積壓在 buffer 中沒有進入 os cache 。
查看日誌發現很多 write 拒絕執行的情況
從日誌中可以看出 ES 的 write 線程池已經滿負荷,執行任務的線程已經達到最大16個線程,而200容量的隊列也已經放不下新的task。
查看線程池的情況也可以看出悔侍 write 線程池有很多寫入的任務
所以我們需要優化 ES 的 write 的性能。
ES 的優化分為很多方面,我們要根據使用場景考慮對 ES 的要求。
根據個人實踐經驗,列舉三種不同場景碧沖吵下的特點 :
這三類場景的特點如下:
關於實時性
可以從三方面進行優化:JVM性能調優、ES性能調優、控制數據來源
可以從三方面進行優化:JVM 性能調優、ES 性能調優、控制數據來源
第一步是 JVM 調優。
因為 ES 是依賴於 JVM 運行,沒有合理的設置 JVM 參數,將浪費資源,甚至導致 ES 很容易 OOM 而崩潰。
(1) 查看 GC 日誌
(2) 使用 jstat 看下每秒的 GC 情況
用下面幾種方式都可查看新、老年代內存大小
(1) 使用 jstat -gc pid 查看 Eden 區、老年代空間大小
(2) 使用 jmap -heap pid 查看 Eden 區、老年代空間大小
(3) 查看 GC 日誌中的 GC 明細
上面的幾種方式都判羨查詢出,新生代總內存約1081M,即1G左右;老年代總內存為19864000K,約19G。新、老比例約1:19,出乎意料。
這真是一個容易踩坑的地方。
如果沒有顯示設置新生代大小,JVM 在使用 CMS 收集器時會自動調參,新生代的大小在沒有設置的情況下是通過計算得出的,其大小可能與 NewRatio 的默認配置沒什麼關系而與 ParallelGCThreads 的配置有一定的關系。
所以: 新生代大小有不確定性,最好配置 JVM 參數 -XX:NewSize、-XX:MaxNewSize 或者 -xmn ,免得遇到一些奇怪的 GC,讓人措手不及。
新生代過小,老年代過大的影響
32G 的內存,分配 20G 給堆內存是不妥當的,所以調整為總內存的50%,即16G。
修改 elasticsearch 的 jvm.options 文件
設置要求:
因為指定新生代空間大小,導致 JVM 自動調參只分配了 1G 內存給新生代。
修改 elasticsearch 的 jvm.options 文件,加上
老年代則自動分配 16G-8G=8G 內存,新生代老年代的比例為 1:1。修改後每次 Young GC 頻率更低,且每次 GC 後只有少數數據會進入老年代。
ES默認使用的垃圾回收器是:老年代(CMS)+ 新生代(ParNew)。如果是JDK1.9,ES 默認使用G1垃圾回收器。
因為使用的是 JDK1.8,所以並未切換垃圾回收器。後續如果再有性能問題再切換G1垃圾回收器,測試是否有更好的性能。
優化前
每秒列印一次 GC 數據。可以看出,年輕代增長速度很快,幾秒鍾年輕代就滿了,導致 Young GC 觸發很頻繁,幾秒鍾就會觸發一次。而每次 Young GC 很大可能有存活對象進入老年代,而且,存活對象多的時候(看上圖中第一個紅框中的old gc數據),有(51.44-51.08)/100 * 19000M = 約68M。每次進入老年代的對象較多,加上頻繁的 Young GC,會導致新老年代的分代模式失去了作用,相當於老年代取代了新生代來存放近期內生成的對象。當老年代滿了,觸發 Full GC,存活的對象也會很多,因為這些對象很可能還是近期加入的,還存活著,所以一次 Full GC 回收對象不多。而這會惡性循環,老年代很快又滿了,又 Full GC,又殘留一大部分存活的,又很容易滿了,所以導致一直頻繁 Full GC。
優化後
每秒列印一次 GC 數據。可以看出,新生代增長速度慢了許多,至少要60秒才會滿,如上圖紅框中數據,進入老年代的對象約(15.68-15.60)/100 * 10000 = 8M,非常的少。所以要很久才會觸發一次 Full GC 。而且等到 Full GC 時,老年代裡很多對象都是存活了很久的,一般都是不會被引用,所以很大一部分會被回收掉,留一個比較干凈的老年代空間,可以繼續放很多對象。
ES 啟動後,運行14個小時
優化前
Young GC 每次的時間是不長的,從上面監控數據中可以看出每次GC時長 1467.995/27276 約等於 0.05秒。那一秒鍾有多少時間實在處理Young GC ? 計算公式:1467秒/ (60秒×60分 14小時)= 約0.028秒,也就是100秒中就有2.8秒在Young GC,也就是有2.8S的停頓,這對性能還是有很大消耗的。同時也可以算出多久一次Young GC, 方程是: 60秒×60分*14小時/ 27276次 = 1次/X秒,計算得出X = 0.54,也就是0.54秒就會有一次Young GC,可見 Young GC 頻率非常頻繁。
優化後
Young GC 次數只有修改前的十分之一,Young GC 時間也是約八分之一。Full GC 的次數也是只有原來的八分之一,GC 時間大約是四分之一。
GC 對系統的影響大大降低,性能已經得到很大的提升。
上面已經分析過ES作為日誌存儲時的特性是:高並發寫、讀少、接受30秒內的延時、可容忍部分日誌數據丟失。
下面我們針對這些特性對ES進行調優。
本人整理了一下數據寫入的底層原理
refresh
ES 接收數據請求時先存入 ES 的內存中,默認每隔一秒會從內存 buffer 中將數據寫入操作系統緩存 os cache,這個過程叫做 refresh;
到了 os cache 數據就能被搜索到(所以我們才說 ES 是近實時的,因為1s 的延遲後執行 refresh 便可讓數據被搜索到)
fsync
translog 會每隔5秒或者在一個變更請求完成之後執行一次 fsync 操作,將 translog 從緩存刷入磁碟,這個操作比較耗時,如果對數據一致性要求不是跟高時建議將索引改為非同步,如果節點宕機時會有5秒數據丟失;
flush
ES 默認每隔30分鍾會將 os cache 中的數據刷入磁碟同時清空 translog 日誌文件,這個過程叫做 flush。
merge
ES 的一個 index 由多個 shard 組成,而一個 shard 其實就是一個 Lucene 的 index ,它又由多個 segment 組成,且 Lucene 會不斷地把一些小的 segment 合並成一個大的 segment ,這個過程被稱為 段merge 。執行索引操作時, ES會先生成小的segment ,ES 有離線的邏輯對小的 segment 進行合並,優化查詢性能。但是合並過程中會消耗較多磁碟 IO,會影響查詢性能。
為了保證不丟失數據,就要保護 translog 文件的安全:
該方式提高數據安全性的同時, 降低了一點性能.
==> 頻繁地執行 fsync 操作, 可能會產生阻塞導致部分操作耗時較久. 如果允許部分數據丟失, 可設置非同步刷新 translog 來提高效率,還有降低 flush 的閥值,優化如下:
寫入 Lucene 的數據,並不是實時可搜索的,ES 必須通過 refresh 的過程把內存中的數據轉換成 Lucene 的完整 segment 後,才可以被搜索。
默認1秒後,寫入的數據可以很快被查詢到,但勢必會產生大量的 segment,檢索性能會受到影響。所以,加大時長可以降低系統開銷。對於日誌搜索來說,實時性要求不是那麼高,設置為5秒或者10s;對於SkyWalking,實時性要求更低一些,我們可以設置為30s。
設置如下:
index.merge.scheler.max_thread_count 控制並發的 merge 線程數,如果存儲是並發性能較好的 SSD,可以用系統默認的 max(1, min(4, availableProcessors / 2)),當節點配置的 cpu 核數較高時,merge 佔用的資源可能會偏高,影響集群的性能,普通磁碟的話設為1,發生磁碟 IO 堵塞。設置max_thread_count 後,會有 max_thread_count + 2 個線程同時進行磁碟操作,也就是設置為 1 允許3個線程。
設置如下:
該方式可對已經生成的索引做修改,但是對於後續新建的索引不生效,所以我們可以製作 ES 模板,新建的索引按模板創建索引。
因為我們的業務日誌是按天維度創建索引,索引名稱示例:user-service-prod-2020.12.12,所以用通配符 202 ..*匹配對應要創建的業務日誌索引。
前文已經提到過,write 線程池滿負荷,導致拒絕任務,而有的數據無法寫入。
而經過上面的優化後,拒絕的情況少了很多,但是還是有拒絕任務的情況。
所以我們還需要優化write線程池。
從 prometheus 監控中可以看到線程池的情況:
為了更直觀看到ES線程池的運行情況,我們安裝了 elasticsearch_exporter 收集 ES 的指標數據到 prometheus,再通過 grafana 進行查看。
經過上面的各種優化,拒絕的數據量少了很多,但是還是存在拒絕的情況,如下圖:
write 線程池如何設置:
參考: ElasticSearch線程池
write 線程池採用 fixed 類型的線程池,也就是核心線程數與最大線程數值相同。線程數默認等於 cpu 核數,可設置的最大值只能是 cpu 核數加1,也就是16核CPU,能設置的線程數最大值為17。
優化的方案:
config/elasticsearch.yml文件增加配置
優化後效果
Swap 交換分區 :
參考: ElasticSearch官方解釋為什麼要禁用交換內存
有三種方式可以實現 ES 不使用Swap分區
執行命令
可以臨時禁用 Swap 內存,但是操作系統重啟後失效
執行下列命令
正常情況下不會使用 Swap,除非緊急情況下才會 Swap。
config/elasticsearch.yml 文件增加配置
分片
索引的大小取決於分片與段的大小,分片過小,可能導致段過小,進而導致開銷增加;分片過大可能導致分片頻繁 Merge,產生大量 IO 操作,影響寫入性能。
因為我們每個索引的大小在15G以下,而默認是5個分片,沒有必要這么多,所以調整為3個。
分片的設置我們也可以配置在索引模板。
副本數
減少集群副本分片數,過多副本會導致 ES 內部寫擴大。副本數默認為1,如果某索引所在的1個節點宕機,擁有副本的另一台機器擁有索引備份數據,可以讓索引數據正常使用。但是數據寫入副本會影響寫入性能。對於日誌數據,有1個副本即可。對於大數據量的索引,可以設置副本數為0,減少對性能的影響。
分片的設置我們也可以配置在索引模板。
有的應用1天生成10G日誌,而一般的應用只有幾百到1G。一天生成10G日誌一般是因為部分應用日誌使用不當,很多大數量的日誌可以不打,比如大數據量的列表查詢介面、報表數據、debug 級別日誌等數據是不用上傳到日誌伺服器,這些 即影響日誌存儲的性能,更影響應用自身性能 。
優化後的兩周內ELK性能良好,沒有使用上的問題:
參考
G. 如何查看java虛擬機堆內存的參數值
請確保java_home/bin配置到path環境變數下,因為這些工具都在jdk的bin目錄下
jps(JVM Process Status Tool):JVM機進程狀況工具
用來查看基於HotSpot JVM裡面所有進程的具體狀態, 包括進程ID,進程啟動的路徑等等。與unix上的ps類似,用來顯示本地有許可權的java進程,可以查看本地運行著幾個java程序,並顯示他們的進程號。使用jps時,不需要傳遞進程號做為參數。
Jps也可以顯示遠程系統上的JAVA進程,這需要遠程服務上開啟了jstat服務,以及RMI注及服務,不過常用都是對本對的JAVA進程的查看。
命令格式:jps [ options ] [ hostid ]
常用參數說明:
-m 輸出傳遞給main方法的參數,如果是內嵌的JVM則輸出為null。
-l 輸出應用程序主類的完整包名,或者是應用程序JAR文件的完整路徑。
-v 輸出傳給JVM的參數。
例如:
C:\Users\Administrator>jps -lmv
1796 -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -XX:MaxPermSize=256m
7340 sun.tools.jps.Jps -lmv -Denv.class.path=.;D:\DevTools\VM\jdk1.6.0_31\\lib\dt.jar;D:\DevTools\VM\jdk1.6.0_31\\lib\tools.jar; -Dapplication.home=D:\DevTools\VM\jdk1.6.0_31 -Xms8m
其中pid為1796的是我的eclipse進程,pid為7340的是jps命令本身的進程
jinfo(Configuration Info for Java):JVM配置信息工具
可以輸出並修改運行時的java 進程的opts。用處比較簡單,用於輸出JAVA系統參數及命令行參數
命令格式:jinfo [ options ] [ pid ]
常用參數說明:
-flag 輸出,修改,JVM命令行參數
例如:
C:\Users\Administrator>jinfo 1796
將會列印出很多jvm運行時參數信息,由於比較長這里不再列印出來,可以自己試試,內容一目瞭然
Jstack(Stack Trace for Java):JVM堆棧跟蹤工具
jstack用於列印出給定的java進程ID或core file或遠程調試服務的Java堆棧信息,如果是在64位機器上,需要指定選項"-J-d64「
命令格式:jstack [ option ] pid
常用參數說明:
-F 當』jstack [-l] pid』沒有相應的時候強制列印棧信息
-l 長列表. 列印關於鎖的附加信息,例如屬於java.util.concurrent的ownable synchronizers列表.
-m 列印java和native c/c++框架的所有棧信息.
-h | -help列印幫助信息
例如:
C:\Users\Administrator>jstack 1796
2013-05-22 11:42:38
Full thread mp Java HotSpot(TM) Client VM (20.6-b01 mixed mode):
"Worker-30" prio=6 tid=0x06514c00 nid=0x1018 in Object.wait() [0x056af000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at org.eclipse.core.internal.jobs.WorkerPool.sleep(WorkerPool.java:188)
- locked <0x1ad84a90> (a org.eclipse.core.internal.jobs.WorkerPool)
at org.eclipse.core.internal.jobs.WorkerPool.startJob(WorkerPool.java:220)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:50)
......
......
......
......
jstat(JVM statistics Monitoriing Tool):JVM統計信息監視工具
對Java應用程序的資源和性能進行實時的命令行的監控,包括了對Heap size和垃圾回收狀況的監控
命令格式:jstat [ option pid [interval [ s | ms ] [count] ] ]
常用參數說明:
-gcutil 輸出已使用空間占總空間的百分比
-gccapacity 輸出堆中各個區域使用到的最大和最小空間
例如:每隔1秒監控jvm內存一次,共監控5次
C:\Users\Administrator>jstat -gccapacity 1796 1s 5
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 96
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 96
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 96
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 96
13632.0 174720.0 40896.0 4032.0 4032.0 32832.0 27328.0 349568.0 81684.0 81684.0 12288.0 262144.0 80640.0 80640.0 42 97
C:\Users\Administrator>jstat -gcutil 1796 1s 5
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
0.00 0.00 0.52 53.35 99.77 42 0.513 99 38.119 38.632
一些術語的中文解釋:
S0C:年輕代中第一個survivor(倖存區)的容量 (位元組)
S1C:年輕代中第二個survivor(倖存區)的容量 (位元組)
S0U:年輕代中第一個survivor(倖存區)目前已使用空間 (位元組)
S1U:年輕代中第二個survivor(倖存區)目前已使用空間 (位元組)
EC:年輕代中Eden(伊甸園)的容量 (位元組)
EU:年輕代中Eden(伊甸園)目前已使用空間 (位元組)
OC:Old代的容量 (位元組)
OU:Old代目前已使用空間 (位元組)
PC:Perm(持久代)的容量 (位元組)
PU:Perm(持久代)目前已使用空間 (位元組)
YGC:從應用程序啟動到采樣時年輕代中gc次數
YGCT:從應用程序啟動到采樣時年輕代中gc所用時間(s)
FGC:從應用程序啟動到采樣時old代(全gc)gc次數
FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)
GCT:從應用程序啟動到采樣時gc用的總時間(s)
NGCMN:年輕代(young)中初始化(最小)的大小 (位元組)
NGCMX:年輕代(young)的最大容量 (位元組)
NGC:年輕代(young)中當前的容量 (位元組)
OGCMN:old代中初始化(最小)的大小 (位元組)
OGCMX:old代的最大容量 (位元組)
OGC:old代當前新生成的容量 (位元組)
PGCMN:perm代中初始化(最小)的大小 (位元組)
PGCMX:perm代的最大容量 (位元組)
PGC:perm代當前新生成的容量 (位元組)
S0:年輕代中第一個survivor(倖存區)已使用的占當前容量百分比
S1:年輕代中第二個survivor(倖存區)已使用的占當前容量百分比
E:年輕代中Eden(伊甸園)已使用的占當前容量百分比
O:old代已使用的占當前容量百分比
P:perm代已使用的占當前容量百分比
S0CMX:年輕代中第一個survivor(倖存區)的最大容量 (位元組)
S1CMX :年輕代中第二個survivor(倖存區)的最大容量 (位元組)
ECMX:年輕代中Eden(伊甸園)的最大容量 (位元組)
DSS:當前需要survivor(倖存區)的容量 (位元組)(Eden區已滿)
TT: 持有次數限制
MTT : 最大持有次數限制
jmap( Memory Map for Java):JVM內存映像工具
列印出某個java進程(使用pid)內存內的所有『對象』的情況(如:產生那些對象,及其數量)
命令格式:jmap [ option ] pid
常用參數說明:
-mp:[live,]format=b,file=<filename> 使用二進制形式輸出jvm的heap內容到文件中, live子選項是可選的,假如指定live選項,那麼只輸出活的對象到文件.
-histo[:live] 列印每個class的實例數目,內存佔用,類全名信息. VM的內部類名字開頭會加上前綴」*」. 如果live子參數加上後,只統計活的對象數量.
-F 強迫.在pid沒有相應的時候使用-mp或者-histo參數. 在這個模式下,live子參數無效.
例如:以二進制形式輸入當前堆內存映像到文件data.hprof中
jmap -mp:live,format=b,file=data.hprof 1796
生成的文件可以使用jhat工具進行分析,在OOM(內存溢出)時,分析大對象,非常有用
通過使用如下參數啟動JVM,也可以獲取到mp文件:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./java_pid<pid>.hprof
在jvm發生內存溢出時生成內存映像文件
jhat(JVM Heap Analysis Tool):JVM堆轉儲快照分析工具
用於對JAVA heap進行離線分析的工具,他可以對不同虛擬機中導出的heap信息文件進行分析,如LINUX上導出的文件可以拿到WINDOWS上進行分析,可以查找諸如內存方面的問題。
命令格式:jhat mpfile(jmap生成的文件)
例如:分析jmap導出的內存映像
jhat data.hprof
執行成功後,訪問http://localhost:7000即可查看內存信息,
MAT(Memory Analyzer Tool):一個基於Eclipse的內存分析工具
官網: http://www.eclipse.org/mat/
update:http://download.eclipse.org/mat/1.2/update-site/
這是eclipse的一個插件,安裝後可以打開xxx.hprof文件,進行分析,比jhat更方便使用,有些時候由於線上xxx.hprof文件過大,直接使用jhat進行初步分析了,可以的話拷貝到本地分析效果更佳。
圖形化監控工具:
在JDK安裝目錄bin下面有兩個可視化監控工具
1. JConsole(Java Monitoring and Management Console) 基於JMX的可視化管理工具。
2. VisualVM(All-in-one Java Troubleshooting Tool)隨JDK發布的最強大的運行監視和故障處理程序。
推薦使用VisualVM,他有很多插件,可以更方便的監控運行時JVM
H. 如何查看 jvm 實際使用的內存數量 jstat
您好,提問者: 在銀豎運行裡面輸入鋒森大cmd 然後輸入jconsole 回車連接就可以了,可能載入有點慢,看你電春液腦配置!
I. jvm如何查找內存問題
JVM 中的內存問題通常是由內存泄漏、內存溢出等引起的。以下是一些 JVM 查找內存問題的方法:
使兆啟芹用 JVM 自帶的工具,如 jmap, jstat, jconsole, jvisualvm 等,來監控和分析 JVM 的內存使用情況。可以查看 JVM 的內存使用情況、對象數量、內存泄漏情況等。
使用垃圾回收日誌來分析內存使用情況。可以通過 -XX:+PrintGC 或 -XX:+PrintGCDetails 參數開啟垃圾回收日誌,並使用分析工具來分析日誌,如 GCViewer, GCEasy, HPROF 等。
使用 Java 代碼來分析內存使用情況。可以使用一些 Java 內存分析工具來分析 JVM 的內存使用情況,如 Eclipse MAT, VisualVM 等。這些工具可以幫助我們查找內存族畢泄漏、對象數量等問題。
使用代碼審查工具。可以使用一些代碼審查工具來查找可旁渣能存在的內存問題,如代碼中未關閉的資源、未釋放的對象等。
查看代碼中的錯誤。可能是由於代碼中的錯誤導致內存問題。例如,可能存在循環引用、使用靜態變數等問題。
J. java程序運行完成之後怎麼看它所用的時間和內存
你要是用tomcat,啟動之後,他會顯示用了多長時間