Java常用的监控命令比如top,jps,jmap等,下面具体讲解一下使用方式

1、top

使用top展示的信息如下所示

java 监控yarn java 监控并发量_java 监控yarn

其中第一行展示了机器的负载(load)信息:当前时间,机器运行了多长时间,有多少登录用户,系统在过去的1分钟,5分钟和15分钟内的平均负载

后面展示了具体进程的使用情况

load average数据是每隔5秒钟检查一次活跃的进程数,

他代表的是当前系统正在运⾏的和处于等待运⾏的进程数之和。也指的是处于可运⾏状态和不可中断状态的平均进程数。

如果单核CPU的话,负载达到1就代表CPU已经达到满负荷的状态了,超过1,后⾯的进⾏就需要排队等待处理了。

如果是是多核多CPU的话,假设现在服务器是2个CPU,每个CPU2个核,那么总负载不超过4都没什么问题。

怎么查看CPU有多少核呢?通过命令cat /proc/cpuinfo | grep "model name" 查看CPU的情况。

通过cat /proc/cpuinfo | grep "cpu cores" 查看CPU的核数

第二行展示了进程调度情况

第三,四,五行分别展示了CPU使用情况,内存占用状态,包括主存与交换分区

CPU 利⽤率:和负载不同,CPU利⽤率指的是当前正在运⾏的进程实时占⽤CPU的百分⽐,他是对⼀段时间内CPU使⽤状况的统计。

CPU负载很⾼,利⽤率却很低:说明处于等待状态的任务很多,负载越⾼,代表可能很多僵死的进程。

通常这种情况是IO密集型的任务,⼤量请求在请求相同的IO,导致任务队列堆积,可以通过命令ps -axjf 查看是否存在状态为D+ 状态的进程,这个状态指的就是不可中断的睡眠状态的进程。处于这个状态的进程⽆法终⽌,也⽆法⾃⾏退出,只能通过恢复其依赖的资源或者重启系统来解决。比如从磁盘读取某一个文件,这个时候突然磁盘驱动不干活了(可能因为取的数据太多驱动没反应过来,也可能因为磁盘出了故障),就会处于D状态

那如果负载很低,利⽤率却很⾼:这表示CPU的任务并不多,但是任务执⾏的时间很⻓,⼤概率就是你写的代码本身有问题,通常是计算密集型任务,⽣成了⼤量耗时短的计算任务。怎么排查?直接top 命令找到使⽤率最⾼的任务,定位到去看看就⾏了。如果代码没有问题,那么过段时间CPU使⽤率就会下降的。

2、jps

java 监控yarn java 监控并发量_中断请求_02

展示了应用程序进程id及启动类名

jsp -l 输出应用程序主类完整package名称或jar完整名称

java 监控yarn java 监控并发量_堆内存_03

这里用的tomcat,可以看到启动的主类就是org.apache.catalina.startup.Bootstrap

jps -v
列出jvm的启动参数,比如 -Djava.util.logging.config.file= -Djava.io.tmpdir= -Dfile.encoding=UTF-8 等参数

3、jinfo

jinfo -flags pid 显示虚拟机版本号,堆内存相关信息,以及启动java进程时使用的命令行

4、jmap

jmap -heap pid 查看堆的使用状况信息,在启动命令中使用 -Xms8G -Xmx8G -XX:+UseG1GC 即可使用G1垃圾收集器

java 监控yarn java 监控并发量_java 监控yarn_04

 

jmap -dump:live,format=b,file=myjmapfile.txt 19570

使用二进制形式输出jvm的heap内容到文件,live子选项是可选的,假如指定live选项,那么只输出活的对象到文件. 

这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用。可以通过-d64来解决(jmap -J-d64 -dump:format=b,file=dump.bin PID) ,而jdk7的某个版本则会抛出异常,这是jdk的bug.

也可以在启动jvm 时添加参数 -Xloggc: 指定gclog的存放位置

5、jstack

jstack可以查看堆栈信息  jstack -l -pid

统计线程数 /opt/java8/bin/jstack -l 28367 | grep 'java.lang.Thread.State' | wc -l

检测死锁:日志中 Found one Java-level deadlock:

java 监控yarn java 监控并发量_TCP_05

查看cpu占用高的线程

1. 通过top 找到占⽤率⾼的进程。

java 监控yarn java 监控并发量_java 监控yarn_06

   

2、通过top -Hp pid 找到占⽤CPU⾼的线程ID。这⾥找到64376的线程ID

java 监控yarn java 监控并发量_TCP_07

再把线程ID转化为16进制, printf "0x%x\n" 3245 ,得到线程ID 0xcad

4. 通过命令jstack 64376 | grep '0xcad' -C5 --color 或者 jstack 64376|vim +/0xcad - 找

到有问题的代码

java 监控yarn java 监控并发量_堆内存_08

6、netstat 查看连接信息

统计已连接上的,状态为“established
netstat -na|grep ESTABLISHED|wc -l

TCP连接状态详解 
LISTEN: 侦听来自远方的TCP端口的连接请求
SYN-SENT: 再发送连接请求后等待匹配的连接请求
SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认
ESTABLISHED: 代表一个打开的连接
FIN-WAIT-1: 等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN-WAIT-2: 从远程TCP等待连接中断请求
CLOSE-WAIT: 等待从本地用户发来的连接中断请求
CLOSING: 等待远程TCP对连接中断的确认
LAST-ACK: 等待原来的发向远程TCP的连接中断请求的确认
TIME-WAIT: 等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED: 没有任何连接状态

线上oom排查方法

1、通过命令查看对应的进程号 比如:jps 或者 ps -ef | grep servicemix

2、输入命令查看gc情况 命令:jstat -gcutil 进程号 刷新的毫秒数 展示的记录数 比如:jstat -gcutil 14050 1000 10 (查看进程号14050,每隔1秒获取下,展示10条记录)

3、查看具体占用情况: (1)命令: jmap -histo 进程号 | more (默认展示到控制台) (2)命令: jmap -histo 14050 | more > exceptionlog.txt (输出到当前目录的exceptionlog.txt文件) 比如:jmap -histo 14050 | more 查看具体的classname,是否有开发人员的类,也可以输出到具体文件分析

补充: oom,先说排查思路,oom是内存溢出,则有堆内存区域溢出,方法区或者元数据区溢出,非堆空间(DirectMemory)溢出 三种场景的情况。 首先通过溢出的异常报错,先确认是哪种类型。

1.如果确认是堆内存区域溢出,可能原因是内存泄露 或者堆空间回收的速度赶不上对象创建的速度,排查方案就是看gc日志,如果是gc频率很高 但是回收对象却很少 就要怀疑是内存泄露,这个时候看dump日志 找到里面占用最多的实体对象,然后再排查代码 为什么这个没回收。 如果是gc频繁,对象也能成功大量回收,但是依然溢出,说明堆空间大小跟不上业务场景的对象创建速度,要么扩大堆空间,要么优化业务场景减少这类对象的产生,为了确认是哪个对象大量产生 也需要jmap 分析dump日志找出是哪个对象,然后看代码针对性优化。

2.方法区或者元数据区溢出,可能是方法区或者元数据区过小,也可能是类过多,需要结合项目里面是否使用了会大量生成类的框架,比如说cglib asm 等,典型的就是aop框架大量生成代理, 可以使用命令 jmap –hisoty more命令查看是哪个类最多。

3.直接内存溢出, 出现在使用unsafe.allocate直接分配内存或者项目里面使用了nio或者nio框架,排查情况比较复杂,原因也有内存泄露 代码不合理等,需要具体情况具体分析,直接内存溢出的典型特征就是dump下来的内存文件很小,但是进程占用的内存空间却很大。 利用的工具和命令有 ps 查找进程ID, jmap dump堆内存文件和分析堆内存 jstat 查看Java进程信息 包括gc 在内