1、Jps查看进程
- 首先查看jps都用哪些命令,使用jps -help帮助查看命令,这样就不用死记硬背了,如下所示:
- 首先用jps命令查看正在运行中的进程的pid等。
-
- jps -l 输出主类的全名,如果进程执行的是 Jar 包,输出 Jar 路径。
- jps -v:输出虚拟机进程启动时 JVM 参数。(经常使用,类似ps - ef |grep java 但比这个显示更清晰)
- jps -m:输出传递给 Java 进程 main() 函数的参数。
2、jstat性能分析(调优使用)
- jstat 命令它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据
- 首先可以自己在Liunx上用jstat -help查看一下有哪些命令可以使用,这个很好用的,不用让我们死记硬背大量的命令了,用法如下:
- 查看jvm内存,以及使用情况(常用)
-
- jstat -gc pid (jps查看进程id)
- 运行这个命令之后大家会看到如下所示:
- 参数解释如下:
- 除了上面jstat -gc是最常用的命令之外,还有一些其他命令,如下所示:
-
- jstat -gccapacity pid:堆内存分析、显示各个代的容量及使用情况;
- jstat -gcnew pid:年轻代GC分析,这个的TT和MTT可以看到对象在年轻代存活的年龄和存活的最大年龄
- stat -class pid:显示 ClassLoader 的相关信息;
- jstat -compiler pid:显示 JIT 编译的相关信息;
- jstat -gcnewcapcacity pid:显示新生代大小与使用情况;
- jstat -gcold pid:显示老年代和永久代的信息;
- jstat -gcoldcapacity pid:显示老年代的大小;
- jstat -gcpermcapacity pid:显示永久代大小;
- jstat -gcutil pid:显示垃圾收集信息;
- 另外,加上 -t参数可以在输出信息上加一个 Timestamp 列,显示程序的运行时间。
- 比如 jstat -gc -h3 31736 1000 10表示分析进程 id 为 31736 的 gc 情况,每隔 1000ms 打印一次记录,打印 10 次停止,每 3 行后打印指标头部。
- jstat使用分析
-
- 首先我们分析线上jvm进程,最想知道哪些信息呢?
- 至少得包括如下,新生代:
-
-
- 新生代对象增长速率
- Young GC的触发频率
- Young GC的耗时
- 每次Yong GC后有多少对象是存活下来的
- 每次Yong GC之后有多少对象进入了老年代
-
-
- 老年代:
-
-
- 老年代对象增长速率
- Full GC 的触发频率
- Full GC的耗时
-
-
- 使用jstat知道了上面的信息,我们就可以合理的分配内存空间,尽可能的让对象留在年轻代被回收,而不是进入老年代,避免频繁的发生Full GC,这就是对JVM最好的性能优化了!
- 计算新生代对象增长速率
-
- 随着系统运行,每秒钟会在年轻代Eden区分配多少对象呢?
- 要分析这个,只需要在Liunx上运行命令: jstat -gc pid 1000 10
- 每隔1000ms(也可几分钟打印一次)也就是1s中打印一行jstat统计信息,一共执行10次停止
- 通过这个命令打印的日志信息,你可以对线上的机器通过固定频率输出的统计信息,观察jvm中Eden中的使用变化
-
-
- 举例:第一秒Eden使用了200M,第二面打印信息使用了204.6M,第三秒打印信息使用了211.2M等,那么就可以推断系统每秒大概新增5M对象
-
- 计算Yong GC触发频率和每次耗时
-
- 通过查看jvm新生代内存的分配大小除以上面观察新生代每秒新增的对象大小,就可以大致分析出来每个多长时间会发生一次Yong GC了
- 那么每次Yong GC的平均耗时呢?
- jstat会告诉你到现在系统已经发生了多少次Yong GC以及这些GC的总耗时,那么就可以计算出GC时会导致系统STW多少时间
- 每次Yong GC之后有多少对象是存活的和进入老年代的
-
- 分析方法也是如上述差不多,可以使用jstat -gc pid 3分钟 10
- 比如3分钟是上面分析出来的Yong GC的频率,那么就可以看下每次Yong GC之后,老年代内存使用率会增加多少
- Full GC触发时机和耗时
-
- 只要知道了老年代对象增长速率,那么FullGc的触发时机就很好算了,用老年代分配的内存除以老年代对象的增长大小就可以算出大概多久老年代会满,会执行一次Full GC
3、Jmap查看内存
- 首先使用jmap -help查看有哪些命令可以使用
3.1、Jmap和Jhat两个最常用的命令
- jmap -histo pid
-
- 这个命令会按照各种对象占用的内存空间大小降序排列,把占用内存最多的队形放在最上面
- 这样就可以看到到底是哪个对象占用了大量的内存空间了
- 使用jmap生成堆内存快照
-
- 上面的方式只能看一个大概,如果想要更详细的看,则用生成堆内存快照的方式
- jmap -dump:live,format=b,file=dump.hprof pid
- 当然file=也可以指定快照生成文件夹,并且生成的文件后缀也可以是.log .bin等之类的,例如我这边测试的如下两种方式:
- 使用jhat分析jvm内存快照
-
- 上面是dump下当前的内存快照,但是他是二进制的我们不方便查看,所以这里可以使用jdk自带的jhat在浏览器上分析
- 使用命令jhat /usr/local/heap.bin 默认端口为7000 (-port 7001 可以指定端口)
- 浏览器访问http://ip:7000,可以详细查看,示例如下:
- 对于jhat启动后显示的html页面中功能:显示出堆中所包含的所有的类
- 详情参考:https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html
3.2、Jmap其他命令
- jmap -histo:live pid
-
- 描述:显示堆中对象的统计信息,其中包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个’*’前缀。如果指定了live子选项,则只计算活动的对象。
- 命令:jmap -clstats pid
-
- 描述:打印类加载器信息 ,-clstats是-permstat的替代方案,在JDK8之前,-permstat用来打印类加载器的数据
打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、 它 所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。
4、Jstack查看线程
- 首先查看帮助jstack -help
4.1、cpu使用率过高
- 可以通过jstack来分析
- 首先使用jps找到需要查看的进程pid
- 接着找出该进程最消耗CPU的线程,可以使用top -Hp 26048或者ps -Lfp 26048来查看该进程中线程的cpu消耗情况
- 查看到线程26094的消耗CPU时间是最长的,用命令查看该线程的十六进制值
[root@dzt-test-5-52 promotion-core]# printf "%x\n" 26094 65ee 查询到的值65ee用于下面jstack 定位信息(jstack 进程号|grep 65ee) [root@dzt-test-5-52 promotion-core]# jstack 26048|grep 65ee "redisson-netty-4-5" #34 prio=5 os_prio=0 tid=0x00007fa3462cd000 nid=0x65ee runnable [0x00007fa2e4bd7000] 这样就可以看到redisson-netty-4-5是最耗时的类,然后就可以去代码审查代码了。