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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

JVM性能调优实践

發(fā)布時(shí)間:2024/1/23 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM性能调优实践 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言
在遇到實(shí)際性能問題時(shí),除了關(guān)注系統(tǒng)性能指標(biāo)。還要結(jié)合應(yīng)用程序的系統(tǒng)的日志、堆棧信息、GClog、threaddump等數(shù)據(jù)進(jìn)行問題分析和定位。關(guān)于性能指標(biāo)分析可以參考前一篇JVM性能調(diào)優(yōu)實(shí)踐——性能指標(biāo)分析。

JVM的調(diào)優(yōu)和故障處理可以使用JDK的幾個(gè)常用命令工具。因?yàn)楸疚氖腔贒ocker容器內(nèi)部的Springboot服務(wù)。需要調(diào)整一下docker容器的啟動(dòng)參數(shù),才可以使用jmap等工具。jmap命令需要使用Linux的Capability的PTRACE_ATTACH權(quán)限。而Docker自1.10在默認(rèn)的seccomp配置文件中禁用了PTRACE_ATTACH。目前使用的Docker version是17.04.0-ce。支持的Capability列表可以詳看runtime-privilege-and-linux-capabilities。?
調(diào)整Capability的方式也比較方便。可以如下直接在運(yùn)行參數(shù)后面加 cap_add,cap-drop

$docker run --cap-add=ALL --cap-drop=MKNOD ...
1
也可以在compose中增加:

? ?cap_add:
? ? ?- ALL
? ?cap_drop:
? ? ?- NET_ADMIN
? ? ?- SYS_ADMIN
1
2
3
4
5
Docker容器中的服務(wù)進(jìn)程
在排查問題時(shí),一般是先通過JVM性能調(diào)優(yōu)實(shí)踐——性能指標(biāo)分析中的幾個(gè)命令來分析基礎(chǔ)的服務(wù)器狀態(tài)和信息。在微服務(wù)架構(gòu)中,每臺(tái)服務(wù)器部署著若干運(yùn)行著服務(wù)的容器。在不能通過應(yīng)用日志或者問題現(xiàn)象定位問題服務(wù)時(shí),需要找到問題容器。?
先通過TOP命令找到耗費(fèi)關(guān)鍵資源的進(jìn)程。

top - 11:45:13 up 318 days, 20:43, ?2 users, ?load average: 0.15, 0.19, 0.18
Tasks: 172 total, ? 1 running, 171 sleeping, ? 0 stopped, ? 0 zombie
%Cpu(s): ?3.1 us, ?1.9 sy, ?0.0 ni, 94.7 id, ?0.0 wa, ?0.0 hi, ?0.3 si, ?0.0 st
KiB Mem: ? 8175392 total, ?7868636 used, ? 306756 free, ? 204400 buffers
KiB Swap: ? ? ? ?0 total, ? ? ? ?0 used, ? ? ? ?0 free. ? 849564 cached Mem

? PID USER ? ? ?PR ?NI ? ?VIRT ? ?RES ? ?SHR S ?%CPU %MEM ? ? TIME+ COMMAND ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
31399 root ? ? ?20 ? 0 3585612 806804 ?12228 S ? 3.0 ?9.9 548:20.94 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?6331 root ? ? ?20 ? 0 3445612 925660 ?15784 S ? 2.7 11.3 ?41:40.29 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
31122 root ? ? ?20 ? 0 3460712 888776 ?11568 S ? 2.0 10.9 484:19.31 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
31147 root ? ? ?20 ? 0 3288180 811476 ?12748 S ? 1.3 ?9.9 263:44.73 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?8506 root ? ? ?20 ? 0 3254088 750880 ? 6116 S ? 1.0 ?9.2 760:45.19 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
22940 root ? ? ?20 ? 0 1029012 ?70584 ?23396 S ? 0.7 ?0.9 ? 0:10.68 node ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
24550 root ? ? ?20 ? 0 1229088 ?43096 ? 8712 S ? 0.7 ?0.5 160:15.74 node ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? 7 root ? ? ?20 ? 0 ? ? ? 0 ? ? ?0 ? ? ?0 S ? 0.3 ?0.0 606:49.74 rcu_sched ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? 454 sshd ? ? ?20 ? 0 ? 32792 ? 1924 ? ?188 S ? 0.3 ?0.0 ?29:15.40 nginx ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
13721 root ? ? ?20 ? 0 ? 25396 ? 1956 ? 1324 S ? 0.3 ?0.0 ?56:29.17 AliYunDunUpdate ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
16225 root ? ? ?20 ? 0 3072752 429296 ? 6848 S ? 0.3 ?5.3 ?42:51.01 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
20795 root ? ? ?20 ? 0 2408848 ?75344 ? 3960 S ? 0.3 ?0.9 ? 2361:22 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
23581 root ? ? ?20 ? 0 ? 16736 ? 2676 ? 2196 R ? 0.3 ?0.0 ? 0:00.01 top ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
31352 root ? ? ?20 ? 0 ?206920 ? 1488 ? 1024 S ? 0.3 ?0.0 ? 1:20.48 docker-containe ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
32000 root ? ? ?20 ? 0 3061760 403708 ? 6548 S ? 0.3 ?4.9 127:01.39 java ? ? ? ??
... 省略其他信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
因?yàn)镈ocker容器中還有java進(jìn)程,所以需要找到具體的父子進(jìn)程id.用ps -ef命令如下所示。第二列是PID(進(jìn)程ID),第三列是PPID(父進(jìn)程ID)。

$ps -ef |grep java?
root ? ? ?6310 ?6293 ?0 May21 ? ? ? ? ?00:00:00 /bin/sh -c java -Dcontainer.host.ip=...
root ? ? ?6331 ?6310 ?2 May21 ? ? ? ? ?00:41:51 java -Dcontainer.host.ip= -server ...?
root ? ? ?8482 ?8465 ?0 Apr16 ? ? ? ? ?00:00:00 /bin/sh -c java -Dcontainer.host.ip...
root ? ? ?8506 ?8482 ?1 Apr16 ? ? ? ? ?12:40:53 java -Dcontainer.host.ip= -server...
... 省略其他信息
1
2
3
4
5
6
可以使用docker inspect查看容器內(nèi)部信息,找到對(duì)應(yīng)的容器實(shí)例的進(jìn)程信息。如下即可打印當(dāng)前宿主機(jī)的所有運(yùn)行的容器實(shí)例的PID,為了方便映射,可以打印對(duì)應(yīng)容器名字,或者容器ID:

## 打印容器pid和容器id
$docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.ID}}' | grep "^${PID}"
## 打印容器pid和容器name?
$ docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.Name}}' | grep "^${PID}" ?
6310, /service-item
31369, /gateway-api
31094, /service-resource
31025, /service-trade
30916, /service-user
16204, /service-analytics
8482, /service-financial
... 省略其他信息
1
2
3
4
5
6
7
8
9
10
11
12
13
如果要分析最消耗內(nèi)存的進(jìn)程,對(duì)應(yīng)的pid= 6331,其所在的docker進(jìn)程id也即父進(jìn)程id= 6310,可以定位出service-item服務(wù)最消耗內(nèi)存資源。定位到服務(wù)之后,即可使用docker exec -it service-item ‘/bin/sh’查看容器內(nèi)部信息。

JVM調(diào)優(yōu)基礎(chǔ)命令
在容器內(nèi)部,就可以進(jìn)一步使用jdk提供的jps、jstack、jstat、jmap等工具來進(jìn)行jvm問題排查和調(diào)優(yōu)。

jps[options] [hostid]
jps主要用來輸出JVM中運(yùn)行的進(jìn)程狀態(tài)信息。

-q 輸出類名、Jar名和傳入main方法的參數(shù)
-m 輸出傳入main方法的參數(shù)
-l 輸出main類或Jar的全限名
-v 輸出傳入JVM的參數(shù)
如下查看運(yùn)行的java進(jìn)程信息,打印jar名以及運(yùn)行main方法傳入的參數(shù):

/opt/app # jps -l -m
6 /opt/app/app.jar --server.port=8080
327 sun.tools.jps.Jps -l -m
1
2
3
4
jstat
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]?
1
jstat命令可以用于持續(xù)觀察虛擬機(jī)內(nèi)存中各個(gè)分區(qū)的使用率以及GC的統(tǒng)計(jì)數(shù)據(jù)。vmid是Java虛擬機(jī)ID,在Linux/Unix系統(tǒng)取進(jìn)程ID。?
如下面輸出的信息,采樣時(shí)間間隔為1000ms,采樣5次:

/opt/app # ?jstat -gc 6 1000 5
?S0C ? ?S1C ? ?S0U ? ?S1U ? ? ?EC ? ? ? EU ? ? ? ?OC ? ? ? ? OU ? ? ? MC ? ? MU ? ?CCSC ? CCSU ? YGC ? ? YGCT ? ?FGC ? ?FGCT ? ? GCT ??
1536.0 1536.0 1233.7 ?0.0 ? 171520.0 169769.2 ?249344.0 ? 57018.6 ? 93912.0 91906.8 11264.0 10853.7 ? 6224 ? 47.439 ? 5 ? ? ?3.423 ? 50.863
1536.0 1536.0 1233.7 ?0.0 ? 171520.0 169805.4 ?249344.0 ? 57018.6 ? 93912.0 91906.8 11264.0 10853.7 ? 6224 ? 47.439 ? 5 ? ? ?3.423 ? 50.863
1536.0 1536.0 ?0.0 ? 1536.0 171520.0 ?3527.9 ? 249344.0 ? 60347.4 ? 96728.0 94808.1 11520.0 11174.7 ? 6225 ? 47.453 ? 5 ? ? ?3.423 ? 50.876
1536.0 1536.0 ?0.0 ? 1536.0 171520.0 ?4742.1 ? 249344.0 ? 60347.4 ? 96728.0 94808.1 11520.0 11174.7 ? 6225 ? 47.453 ? 5 ? ? ?3.423 ? 50.876
1536.0 1536.0 ?0.0 ? 1536.0 171520.0 ?7589.3 ? 249344.0 ? 60347.4 ? 96728.0 94808.1 11520.0 11174.7 ? 6225 ? 47.453 ? 5 ? ? ?3.423 ? 50.876
1
2
3
4
5
6
7
8
上述各個(gè)列的含義:

S0C、S1C、S0U、S1U:young代的Survivor 0/1區(qū)容量(Capacity)和使用量(Used)。0是FromSurvivor,1是ToSurvivor。
EC、EU:Eden區(qū)容量和使用量
OC、OU:年老代容量和使用量
MC、MU:元數(shù)據(jù)區(qū)(Metaspace)已經(jīng)committed的內(nèi)存空間和使用量
CCSC、CCSU:壓縮Class(Compressed class space)committed的內(nèi)存空間和使用量。
YGC、YGT:young代GC次數(shù)和GC耗時(shí)
FGC、FGCT:Full GC次數(shù)和Full GC耗時(shí)
GCT:GC總耗時(shí)
可以通過分區(qū)占用量上看到,在第2-3秒之間發(fā)生了一次YGC。YGC次數(shù)+1,并且Survivor from區(qū)的內(nèi)存空間從1233.7->0,Survivor from從0->1536。Eden區(qū)也釋放了很多內(nèi)存空間。其他變化的空間占用也有元數(shù)據(jù)區(qū)以及元數(shù)據(jù)區(qū)的壓縮Class區(qū)。Compressed class space也是元數(shù)據(jù)區(qū)的一部分,默認(rèn)是1G,也可以關(guān)閉。具體的jvm8內(nèi)存分布不再詳述。下一篇GC優(yōu)化會(huì)再展開整理下。?
如果只看gc的總統(tǒng)計(jì)信息,也可以用jstat -gcutil vmid查詢:

/opt/app # jstat -gcutil 6?
? S0 ? ? S1 ? ? E ? ? ?O ? ? ?M ? ? CCS ? ?YGC ? ? YGCT ? ?FGC ? ?FGCT ? ? GCT ??
? 0.00 100.00 ?73.76 ?24.20 ?98.02 ?97.00 ? 6225 ? 47.453 ? ? 5 ? ?3.423 ? 50.876 ?
1
2
3
jmap [option] pid
jmap可以用來查看堆內(nèi)存的使用詳情。內(nèi)存各個(gè)分區(qū)可以通過jmap -heap pid來查看。得到的輸出如下:

$jmap -heap 6
Attaching to process ID 6, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.121-b13

using thread-local object allocation.
Parallel GC with 2 thread(s)

Heap Configuration:
? ?MinHeapFreeRatio ? ? ? ? = 0
? ?MaxHeapFreeRatio ? ? ? ? = 100
? ?MaxHeapSize ? ? ? ? ? ? ?= 536870912 (512.0MB)
? ?NewSize ? ? ? ? ? ? ? ? ?= 44564480 (42.5MB)
? ?MaxNewSize ? ? ? ? ? ? ? = 178782208 (170.5MB)
? ?OldSize ? ? ? ? ? ? ? ? ?= 89653248 (85.5MB)
? ?NewRatio ? ? ? ? ? ? ? ? = 2
? ?SurvivorRatio ? ? ? ? ? ?= 8
? ?MetaspaceSize ? ? ? ? ? ?= 21807104 (20.796875MB)
? ?CompressedClassSpaceSize = 1073741824 (1024.0MB)
? ?MaxMetaspaceSize ? ? ? ? = 17592186044415 MB
? ?G1HeapRegionSize ? ? ? ? = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
? ?capacity = 170393600 (162.5MB)
? ?used ? ? = 99020080 (94.43290710449219MB)
? ?free ? ? = 71373520 (68.06709289550781MB)
? ?58.11255821814904% used
From Space:
? ?capacity = 4194304 (4.0MB)
? ?used ? ? = 786432 (0.75MB)
? ?free ? ? = 3407872 (3.25MB)
? ?18.75% used
To Space:
? ?capacity = 4194304 (4.0MB)
? ?used ? ? = 0 (0.0MB)
? ?free ? ? = 4194304 (4.0MB)
? ?0.0% used
PS Old Generation
? ?capacity = 255328256 (243.5MB)
? ?used ? ? = 65264912 (62.24147033691406MB)
? ?free ? ? = 190063344 (181.25852966308594MB)
? ?25.561178783126927% used

39531 interned Strings occupying 4599760 bytes.
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
46
47
Heap Configuration是堆內(nèi)存的配置信息。可以通過運(yùn)行參數(shù)改變。一般通過分析內(nèi)存分布和使用情況以及GC信息,可以針對(duì)不同的應(yīng)用不斷調(diào)整到合適的堆內(nèi)存分區(qū)配置。?
Heap Usage可以看堆內(nèi)存實(shí)時(shí)的占用情況。

使用jmap -histo[:live] pid查看堆內(nèi)存中的對(duì)象的數(shù)目,占用內(nèi)存(單位是byte),如果帶上live則只統(tǒng)計(jì)活對(duì)象,如下:

/opt/app/logs # jmap -histo:live 6 | more

?num ? ? #instances ? ? ? ? #bytes ?class name
----------------------------------------------
? ?1: ? ? ? ?127610 ? ? ? 19132008 ?[C
? ?2: ? ? ? ? ?6460 ? ? ? ?4074512 ?[B
? ?3: ? ? ? ? 37041 ? ? ? ?3259608 ?java.lang.reflect.Method
? ?4: ? ? ? ?125182 ? ? ? ?3004368 ?java.lang.String
? ?5: ? ? ? ? 86616 ? ? ? ?2771712 ?java.util.concurrent.ConcurrentHashMap$Node
? ?6: ? ? ? ? 70783 ? ? ? ?2265056 ?java.util.HashMap$Node
? ?7: ? ? ? ? 17686 ? ? ? ?1967496 ?java.lang.Class
? ?8: ? ? ? ? 15834 ? ? ? ?1448440 ?[Ljava.util.HashMap$Node;
? ?9: ? ? ? ? 35360 ? ? ? ?1414400 ?java.util.LinkedHashMap$Entry
? 10: ? ? ? ? 21948 ? ? ? ?1231624 ?[Ljava.lang.Object;
? 11: ? ? ? ? ?9940 ? ? ? ?1165728 ?[I
? 12: ? ? ? ? ? 986 ? ? ? ?1064480 ?[Ljava.util.concurrent.ConcurrentHashMap$Node;
? 13: ? ? ? ? 18685 ? ? ? ?1046360 ?java.util.LinkedHashMap
? 14: ? ? ? ? 30351 ? ? ? ? 971232 ?java.lang.ref.WeakReference
? 15: ? ? ? ? 50340 ? ? ? ? 805440 ?java.lang.Object
? 16: ? ? ? ? 13490 ? ? ? ? 539600 ?java.lang.ref.SoftReference
? 17: ? ? ? ? 17705 ? ? ? ? 513768 ?[Ljava.lang.String;
? 18: ? ? ? ? 18781 ? ? ? ? 450744 ?org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource$DefaultCacheKey
? 19: ? ? ? ? 20272 ? ? ? ? 434456 ?[Ljava.lang.Class;
? 20: ? ? ? ? 17270 ? ? ? ? 414480 ?java.beans.MethodRef
? 21: ? ? ? ? 23616 ? ? ? ? 377856 ?java.lang.Integer
? 22: ? ? ? ? 11192 ? ? ? ? 358144 ?java.util.LinkedList
? 23: ? ? ? ? 14911 ? ? ? ? 357864 ?java.util.ArrayList
? 24: ? ? ? ? ?5700 ? ? ? ? 319200 ?java.beans.MethodDescriptor


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
以上示例的排序是按照占用內(nèi)存字節(jié)數(shù)倒序的。class name列中”[C,[B,[I “是代表char,byte,int.”[L+類名”代表其他實(shí)例。這種寫法跟Class文件的Java的類型表述含義是一致的。

在進(jìn)行問題排查時(shí),可以使用jmap把進(jìn)程內(nèi)存使用情況dump到文件中,或者dump**.hprof**文件,在本地使用MAT(Eclipse Memory Analyzer)進(jìn)行分析。也可以直接用jhat分析查看。

/opt/app# jmap -dump:format=b,file=heapdump 6
Dumping heap to /opt/app/logs/heapdump ...
Heap dump file created ? ? ? ?


/opt/app# jmap -dump:live,format=b,file=heapLive.hprof 6 ?
1
2
3
4
5
6
jstack [option] pid
jstack可以用來查看Java進(jìn)程內(nèi)的線程堆棧信息。

-l long listings,會(huì)打印出額外的鎖信息,在發(fā)生死鎖時(shí)可以用jstack -l pid來觀察鎖持有情況?
-m mixed mode,不僅會(huì)輸出Java堆棧信息,還會(huì)輸出C/C++堆棧信息(比如Native方法)

輸出信息如下:

/opt/app # jstack -l 6
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):

"elasticsearch[Oneg the Prober][listener][T#1]" #221 daemon prio=5 os_prio=0 tid=0x00007fc2a418a800 nid=0x195 waiting on condition [0x00007fc28318d000]
? ?java.lang.Thread.State: WAITING (parking)
? ? at sun.misc.Unsafe.park(Native Method)
? ? - parking to wait for ?<0x00000000e29f88d0> (a java.util.concurrent.LinkedTransferQueue)
? ? at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
? ? at java.util.concurrent.LinkedTransferQueue.awaitMatch(LinkedTransferQueue.java:737)
? ? at java.util.concurrent.LinkedTransferQueue.xfer(LinkedTransferQueue.java:647)
? ? at java.util.concurrent.LinkedTransferQueue.take(LinkedTransferQueue.java:1269)
? ? at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
? ? at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
? ? at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
? ? at java.lang.Thread.run(Thread.java:745)

? ?Locked ownable synchronizers:
? ? - None
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在線上問題排查線程鎖信息時(shí),jstack是個(gè)非常好用的工具,結(jié)合應(yīng)用日志可以迅速定位到問題線程。

Java性能分析工具
對(duì)于Java性能調(diào)優(yōu),以前一直比較好用的工具是JRockit,JProfile(商業(yè))等工具,但隨著JDK7 up40版本之后,jdk會(huì)自帶JMC(JavaMissionControl)工具。可以分析本地應(yīng)用以及連接遠(yuǎn)程ip使用。提供了實(shí)時(shí)分析線程、內(nèi)存,CPU、GC等信息的可視化界面。從jdk8 up40開始,JMC還提供了在運(yùn)行時(shí)創(chuàng)建JFR記錄(飛行記錄器)。如果是全面分析heap dump,再綜合使用MAT(Eclipse Memory Analyzer)。基本就可以做很多日常的性能調(diào)優(yōu)以及線上問題排查了。下文簡(jiǎn)單介紹一些JMC,基于java version “1.8.0_60”。

Java Mission Control
在Mac上使用的話,需要先找到j(luò)dk中的jmc路徑。

$find /Library/Java -name missioncontrol ??
1
2
在我本地的目錄是/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/missioncontrol/。打開jmc之后,常用的話可以留在dock下面。?
啟動(dòng)需要觀察的應(yīng)用,然后即可在JMC的MBean服務(wù)器中觀察到綜合信息如下:?


進(jìn)一步觀察內(nèi)存以及GC的情況,視圖如下,可以觀察到運(yùn)行時(shí)內(nèi)存各個(gè)分區(qū)的占用率。對(duì)于“堆直方圖”默認(rèn)是不開啟的,可以通過右上角的刷新值來啟用,會(huì)影響性能。一般用于排查內(nèi)存中的大對(duì)象的回收問題以及OOM問題時(shí)可以開啟觀察。

對(duì)于線程死鎖、線程池資源方面的分析,可以到線程視圖中觀察活動(dòng)線程。

Java飛行記錄器(Java Flight Recorder)
Java 8 up40開始,可以使用JMC創(chuàng)建JFR記錄。JFR可以采樣分析收集Java應(yīng)用程序以及JVM的信息, 它的最小開銷小于2%,不會(huì)影響其他JVM優(yōu)化。JFR不會(huì)記錄所有方法調(diào)用,只會(huì)探測(cè)熱點(diǎn)方法,但不包含Native方法的線程采樣。如果要開啟JFR,需要應(yīng)用啟動(dòng)參數(shù)中添加:

?-XX:+UnlockCommertialFeatures -XX:+FlightRecorder ??
1
一般還是建議本地調(diào)優(yōu)和分析時(shí)使用。JFR可以提供固定時(shí)間的采樣(默認(rèn)是1min),以及持續(xù)時(shí)間的記錄。它們都會(huì)dump到一個(gè)“.jfr”的文件中。?
分析內(nèi)存信息如下,可以看到內(nèi)存使用量,以及基礎(chǔ)的GC配置和統(tǒng)計(jì)信息:?

詳細(xì)分析內(nèi)存情況時(shí),需要進(jìn)一步查看“內(nèi)存分配”以及“對(duì)象統(tǒng)計(jì)信息”。其中“對(duì)象統(tǒng)計(jì)信息”也是默認(rèn)不開啟的,需要在創(chuàng)建jfr時(shí)選擇“啟用”如下:?

然后即可看到對(duì)象統(tǒng)計(jì)信息:?


對(duì)于熱點(diǎn)方法以及熱點(diǎn)線程的采樣分析圖表也很直觀,在分析一些循環(huán)調(diào)用時(shí)可以重點(diǎn)關(guān)注熱點(diǎn)方法,對(duì)于有問題的熱點(diǎn)方法可以進(jìn)一步查看“堆棧跟蹤”下的調(diào)用鏈:?


總結(jié)
本文主要介紹了java常用的性能優(yōu)化和排查問題的工具,以及JavaMissionControl工具的一些功能。JMC是官方提供的免費(fèi)工具,結(jié)合MAT,基本可以處理性能優(yōu)化的80%場(chǎng)景。JMC還可以鏈接遠(yuǎn)程ip進(jìn)行分析。但對(duì)于線上問題排查,還是建議使用jstat,jstack,jmap工具等,結(jié)合top、vmstat等快速排查和定位問題。?
性能排查一般問題都集中在cpu、內(nèi)存。前者分析線程,后者分析具體出現(xiàn)問題的內(nèi)存分區(qū)。對(duì)于磁盤、IO等資源瓶頸需要綜合很多業(yè)務(wù)場(chǎng)景進(jìn)行具體定位。
---------------------?
作者:珠寶壹佰.未聞?
來源:CSDN?
原文:https://blog.csdn.net/lijingyao8206/article/details/80432402?
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!

總結(jié)

以上是生活随笔為你收集整理的JVM性能调优实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。