命令行
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
网友评论