命令行
java程序運行過程中出現性能問題可以使用JDK命令行定位問題。下圖針對HotSpot虛擬機的命令行。
名稱 | 描述 | 作用 |
---|---|---|
jps | JVM Process Status Tool | 顯示虛擬機進程 |
jstat | JVM Statistics Monitoring Tool | 收集虛擬機運行時數據 |
jinfo | Configuration Info for Java | 顯示虛擬機配置信息,動態修改一些配置 |
jmap | Memory Map for Java | 生成虛擬機內存轉儲快照(heapdump文件) |
jhat | JVM Heap Dump Browser | 用于分析heapdump文件 |
jstack | Stack Trace for Java | 顯示虛擬機的線程快照 |
實踐
下面是測試代碼
public class ThreadLocalDemo {
private static final ThreadLocal<String> t = new ThreadLocal();
// 父線程變量傳遞給子線程
private static final InheritableThreadLocal<String> subT = new InheritableThreadLocal<>();
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) {
subT.set("main");
Thread thread = new Thread();
executor.submit(() -> {
t.set("hello1");
while (true) {
System.out.println(Thread.currentThread().getName() + " " + t.get());
System.out.println(subT.get());
Thread.sleep(1000);
}
});
executor.submit(() -> {
t.set("hello2");
while (true) {
System.out.println(Thread.currentThread().getName() + " " + t.get());
System.out.println(subT.get());
Thread.sleep(1000);
}
});
executor.shutdown();
}
}
jps
顯示虛擬機進程
jps [options] [hostid]
lucy@localhost:~$jps -l
817 sun.tools.jps.Jps
803 org.jetbrains.jps.cmdline.Launcher
804 com.redoor.thread.ThreadLocalDemo
556
604 org.jetbrains.idea.maven.server.RemoteMavenServer
選項 | 作用 |
---|---|
-q | 只輸出LVMID,省略主類名稱 |
-m | 輸出虛擬機進程啟動時傳遞給主類main()的參數 |
-l | 輸出主類的全名,如果進程執行的時jar,輸出jar的路徑 |
-v | 輸出虛擬機進程啟動時JVM參數 |
jstat
jstat
監控虛擬機運行數據
jstat option vmid [<interval> [<count>]]
# 每100ms輸出804進程ID的gc情況,共輸出10ci
jstat -gcutil 804 100 10
lucy@localhost:~$jstat -gcutil 804
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 0.00 30.29 0.00 17.65 19.90 0 0.000 0 0.000 0.000
S0、S1:兩個Survivor區
E:Eden區
O:老生代
M:Metaspace
YGC:Minor GC執行次數
FGC:Full GC執行次數
YGCT:Minor GC總耗時
FGCT:Full GC總耗時
# 監控gc最大、最小使用內存,單位是kb
jstat -gccapacity 804
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
1398272.0 1398272.0 1398272.0 179712.0 172032.0 1046528.0 2796544.0 2796544.0 2796544.0 2796544.0 21504.0 1048576.0 117248.0 117248.0 1121 165
選項 | 作用 |
---|---|
-class | 監視類裝載、卸載數量、總空間以及類裝載所耗費的時間 |
-gc | 監視Java堆狀態 |
-compiler | 輸出JIT編譯過的方法、耗時等信息 |
-printcompilation | 輸出已經被JIT編譯的方法 |
jinfo
1.查看虛擬機參數的配置
lucy@localhost:~$jinfo -flag ThreadStackSize 916
-XX:ThreadStackSize=1024
2.不重啟jvm情況下修改參數,參考jinfo-運行時查看JVM配置及更改
格式 | 示例 | 描述 |
---|---|---|
jinfo -flag [+|-]<name> pid |
jinfo -flag +PrintGCDetails 2368 |
增加gc日志 |
jinfo -flag <name>=<value> pid |
jinfo -flag PrintGC=1 2368 |
增加gc日志 |
jmap
生成內存堆轉儲快照
jmap [option] vmid
lucy@localhost:~$jmap -dump:format=b,file=a 916
Dumping heap to /Users/lucy/a ...
Heap dump file created
選項 | 作用 |
---|---|
-dump | 生成Java堆轉儲快照 |
-finalizerinfo | 顯示在F-Queue中等待Finalizer線程執行finalize方法的對象,Linux/Solaris平臺有效 |
-heap | 顯示Java堆詳細信息,如使用那種回收器、參數配置、分代狀況等,Linux/Solaris平臺有效 |
-histo | 顯示堆中對象統計信息,包括類、實例數量、合計容量 |
-F | 當虛擬機進程對-dump選項沒有響應時,可使用該選項強制生成dump快照,Linux/Solaris平臺有效 |
jhat
解析堆轉儲快照,并提供服務器訪問
lucy@localhost:~/Desktop$jhat a
Reading from a...
Dump file created Fri Nov 01 13:56:10 CST 2019
Snapshot read, resolving...
Resolving 60018 objects...
Chasing references, expect 12 dots............
Eliminating duplicate references............
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
jstack
生成線程轉儲快照
jstack [option] vmid
lucy@localhost:~$jstack -l 916
2019-11-01 13:59:28
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.191-b12 mixed mode):
"Attach Listener" #16 daemon prio=9 os_prio=31 tid=0x00007f8170a7a800 nid=0x1507 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
...
選項 | 作用 |
---|---|
-F | 強制輸出線程堆棧 |
-l | 除堆棧外,顯示關于鎖的附加信息 |
-m | 如果調用本地方法的話,顯示C/C++的堆棧 |
問題
java程序cpu飆高定位
先找到占用CPU高的進程,然后找到進程里占用CPU高的線程。將線程ID轉為16進制。使用jstack查找該進程ID的情況。
ps -mp pid -o pid,tid
mac上ps和linux的不一樣,mac找不到tid這個關鍵字
jmc使用
java mission control
Mac無法使用jmc,需要替換jar后方可使用。參考JMC(Java Mission Control)在mac下無法啟動和顯示界面。系統版本是10.12.6
,jar包我替換成3.105.2
就可以了。
服務端開啟飛行記錄器
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
# 遠程服務需要綁定ip
-Dcom.sun.management.jmxremote.port=port
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=serverip
客戶端啟動jmc,新建連接。輸入ip和port。如果是本地的話不用新建連接,jvm瀏覽器會自動識別本機的java程序。
引用
https://my.oschina.net/u/2250599/blog/1505661
https://www.cnblogs.com/smail-bao/p/6029619.html
http://calvin1978.blogcn.com/articles/perf-tunning-2.html