jps(Java Virtual Machine Process Status Tool)
jstack(查看线程)、jmap(查看内存)和jstat(性能分析)
jps
jps 找到对应的进程ID
jps -m -l
1 | -q 不输出类名、Jar名和传入main方法的参数 |
ll /proc/[pid]/ | grep exe
可以查到时哪一个后台进程在执行
未重启的话,分析现在的时候:
jstack 线程问题
ps -mp [pid] -o THREAD,tid,time |sort -rn 打印CPU最高的线程
top -Hp [pid]
printf “%x\n” 22338 把线程ID转换成16进制
5742
jstack [pid] | grep 5742 -A 30 打印堆栈信息
-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)
-F to force a thread dump. Use when jstack
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
线程死锁:
jstack –l pid | grep -i –E ‘BLOCKED | deadlock’
jmap 堆问题
jmap -heap [pid] 先查看堆栈
1 | [root@localhost bin]# ./jmap -heap 22327 |
查看对象
用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象,如下:
数量和容量
实例数量前十的类:jmap -histo pid | sort -n -r -k 2 | head -10
实例容量前十的类:jmap -histo pid | sort -n -r -k 3 | head -10
生成hprof文件(hprof(Heap/CPU Profiling Tool))
./jmap -dump:live,format=b,file=dump.dump [pid]
可以用:./jhat -port 9998 dump.dump
./jhat -J-Xmx512m -port 9998 dump.dump
jhat -port 7401 -J -Xmx4G dump.dump
或者dump文件修改为dump.hprof,可以加到jprofiler
作用:主要分析内部当时的对象。
jstat
jstat(JVM统计监测工具)
每隔250ms采集4次./jstat -gc 30359 250 4
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
区容量(Capacity)和使用量(Used)
S0 S1 Survivor E O Eden Old M MetaspaceSize CCS CompressedClassSpaceSize YG young gc FG full gc T time FCT full gc time
./jstat -options
参数 -gc
250ms调用4次
1 | [root@localhost bin]# ./jstat -gc 22327 250 4 |
准备重启复现的话:
第一步 加参数 :
gc日志 配置Catalina.bat JAVA_OPTS
-Xloggc:./logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=32 -XX:GCLogFileSize=64m -XX:+HeapDumpOnOutOfMemoryError
一 线上常见问题定位
常见问题 1:CPU 利用率高
CPU 使用率是衡量系统繁忙程度的重要指标,一般情况下单纯的 CPU 高并没有问题,它代表系统正在不断的处理我们的任务,但是如果 CPU 过高,导致任务处理不过来,从而引起 load 高,这个是非常危险需要关注的。 CPU 使用率的安全值没有一个标准值,取决于你的系统是计算密集型还是 IO 密集型,一般计算密集型应用 CPU 使用率偏高 load 偏低,IO 密集型相反。
问题原因及定位:
1 频繁 FullGC/YongGC
2 代码消耗,如死循环,md5 等内存态操作
常见问题 2:load 高
load 指单位时间内活跃进程数,包含运行态(runnable 和 running)和不可中断态( IO、内核态锁)。关键字是运行态和不可中断态,运行态可以联想到 Java 线程的 6 种状态,如下,线程 new 之后处于 NEW 状态,执行 start 进入 runnable 等待 CPU 调度,因此如果 CPU 很忙会导致 runnable 进程数增加;不可中断态主要包含网络 IO、磁盘 IO 以及内核态的锁,如 synchronized 等。
问题原因及定位:
1 CPU 利用率高,可运行态进程数多
2 iowait,等待 IO
3 等待内核态锁,如 synchronized
常见问题 3:持续 FullGC
问题原因及定位:
1 prommotion failed
从S区晋升的对象在老年代也放不下导致 FullGC(fgc 回收无效则抛 OOM)。
1)survivor 区太小,对象过早进入老年代。
2)大对象分配,没有足够的内存。
日志查找关键字 “allocating large”;
2 concurrent mode failed
在 CMS GC 过程中业务线程将对象放入老年代(并发收集的特点)内存不足。详细原因:
1)fgc 触发比例过大,导致老年代占用过多,并发收集时用户线程持续产生对象导致达到触发 FGC 比例。
jinfo 查看 CMSInitiatingOccupancyFraction 参数,一般 70~80 即可
2)老年代存在内存碎片。
jinfo 查看 UseCMSCompactAtFullCollection 参数,在 FullGC 后整理内存
常见问题 4:线程池满
Java 线程池以有界队列的线程池为例,当新任务提交时,如果运行的线程少于 corePoolSize,则创建新线程来处理请求。如果正在运行的线程数等于 corePoolSize 时,则新任务被添加到队列中,直到队列满。当队列满了后,会继续开辟新线程来处理任务,但不超过 maximumPoolSize。当任务队列满了并且已开辟了最大线程数,此时又来了新任务,ThreadPoolExecutor 会拒绝服务。
问题原因及定位:
2 数据库慢 sql 或者数据库死锁
日志关键字 “Deadlock found when trying to get lock”
Jstack 或 zprofiler 查看阻塞态线程
3 Java 代码死锁
jstack –l pid | grep -i -E ‘BLOCKED | deadlock’