Java - 手撸线上故障 OOM + CPU居高不下

简介: Java - 手撸线上故障 OOM + CPU居高不下

20200620150738463.png

Pre


当你的应用没有一套完善的监控告警系统,线上故障了 ,总是很被动,但是还得要定位问题 ,奈何手里无利器 ,没办法只能硬上了,虽然原始,好在有效~


所以原生的命令你需要特别熟悉,故障的时间很宝贵,所以留给我们翻资料的时间并不多 ~


如果你还不是很了解JVM提供的诊断命令, 戳这里–> JVM-10虚拟机性能监控与故障处理工具之【JDK的命令行】



常见故障

OOM


OOM了 , 但是你没有配置

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/dump/heapdump.hprof  -XX:OnOutOfMemoryError=/opt/restart.sh


重要的参数


-XX:+HeapDumpOnOutOfMemoryError : 表示当JVM发生OOM时,自动生成DUMP文件 最重要的参数,剩余两个参数可选

-XX:HeapDumpPath : 表示生成DUMP文件的路径, 可以指定文件名称, -XX:HeapDumpPath=${目录}/java_heapdump.hprof。若不指定文件名,默认为:java_<pid>_<date>_<time>_heapDump.hprof

-XX:OnOutOfMemoryError : 表示OOM时 需要触发的脚本,比如 重启动作,发送告警等等 用户自定义


或者GC很厉害,你怀疑有内存泄漏的地方 要看堆信息


那你需要谁呢?


  1. jmap Java 内存映射工具 + jhat 虚拟机堆转储快照分析工具
  2. jmap Java 内存映射工具 + MAT (推荐)


jmap Java 内存映射工具

概述

20180806204222611.png


语法及使用

Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)
where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system


jmap的主要选项


image.png


使用举例, 对pid=12888的进程输出dump信息

E:\Program Files\Java\jdk1.8.0_161\bin>jmap -dump:format=b,file=test.bin 12888
Dumping heap to E:\Program Files\Java\jdk1.8.0_161\bin\test.bin ...
Heap dump file created

jhat 虚拟机堆转储快照分析工具

概述


20180806205108530.png

语法及使用

Usage:  jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>
        -J<flag>          Pass <flag> directly to the runtime system. For
                          example, -J-mx512m to use a maximum heap size of 512MB
        -stack false:     Turn off tracking object allocation call stack.
        -refs false:      Turn off tracking of references to objects
        -port <port>:     Set the port for the HTTP server.  Defaults to 7000
        -exclude <file>:  Specify a file that lists data members that should
                          be excluded from the reachableFrom query.
        -baseline <file>: Specify a baseline object dump.  Objects in
                          both heap dumps with the same ID and same class will
                          be marked as not being "new".
        -debug <int>:     Set debug level.
                            0:  No debug output
                            1:  Debug hprof file parsing
                            2:  Debug hprof file parsing, no server
        -version          Report version number
        -h|-help          Print this help and exit
        <file>            The file to read
For a dump file that contains multiple heap dumps,
you may specify which dump in the file
by appending "#<number>" to the file name, i.e. "foo.hprof#3".
All boolean options default to "true"


用法举例

E:\Program Files\Java\jdk1.8.0_161\bin>jmap -dump:format=b,file=test.bin 12888
Dumping heap to E:\Program Files\Java\jdk1.8.0_161\bin\test.bin ...
File exists
E:\Program Files\Java\jdk1.8.0_161\bin>jhat test.bin
Reading from test.bin...
Dump file created Mon Aug 06 20:49:25 CST 2018
Snapshot read, resolving...
Resolving 244224 objects...
Chasing references, expect 48 dots................................................
Eliminating duplicate references................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.


浏览器输入 http://localhost:7000/



20180806205311610.png



MAT

jmap导出的堆内存信息,如果有MAT, 更方便直观 ,推荐


CPU居高不下

传统步骤


top -c ( -c 显示整个命令行而不只是显示命令名 ) ,查看占用cpu的进程

shift+p 按照CPU消耗大小 给进程排序, 找到对应的PID 【P 根据CPU使用百分比大小进行排序】

top -Hp <PID> 具体占用cpu利用率最高的线程号tid ,shift+p 按照CPU消耗大小【H 线程模式 】

print "%\n" tid 【将获取到的线程号转换成16进制】, 用于导出的线程堆栈中根据该关键字查到对应的线程信息 (或者 printf "%x\n" tid)

jstack -l <PID> >001.log 多执行几次 【-l 附带输出锁的信息】

去log中取查找 第四步中转换出来的16进制的内容,看看相应的代码


总结下 ,top 找到 占用CPU最高的 PID, 然后使用top的H参数 线程模式 ,查找到最占用CPU的 TID , 这个tid 是十进制的, jstack导出来的tid是16进制,因此需要转成16进制 ,然后多执行几次jstack , 如果每次都有这个玩意,基本没跑了


附送一篇 Java - 死锁 Dead Lock 定位分析


jstack Java堆栈跟踪工具

概述


20180806205801143.png

语法及使用

Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)
Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -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的主要选项


image.png


用法举例

E:\Program Files\Java\jdk1.8.0_161\bin>jstack -l 12888
2018-08-06 21:01:10
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.51-b03 mixed mode):
"DestroyJavaVM" prio=6 tid=0x000000000e1ab800 nid=0x2f80 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
   Locked ownable synchronizers:
        - None
"DefaultQuartzScheduler_QuartzSchedulerThread" prio=6 tid=0x000000000e1a9800 nid=0xb5c in Object.wait() [0x000000000f59f000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:410)
        - locked <0x0000000762395018> (a java.lang.Object)
   Locked ownable synchronizers:
        - None
......
.......
..........


线上分析工具

https://fastthread.io/


20200620165102598.png


高阶工具 Arthas

https://alibaba.github.io/arthas/arthas-tutorials?language=cn


20200620152433238.png

Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。


当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:


这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?


我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?


遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?


线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!


是否有一个全局视角来查看系统的运行状况?


有什么办法可以监控到JVM的实时运行状态?


怎么快速定位应用的热点,生成火焰图?


Arthas支持JDK 6+,支持Linux/Mac/Winodws,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。


后续单独开篇介绍Arthas 这个牛逼的工具的使用及原理。

相关文章
|
2月前
|
缓存 JavaScript Java
常见java OOM异常分析排查思路分析
Java虚拟机(JVM)遇到内存不足时会抛出OutOfMemoryError(OOM)异常。常见OOM情况包括:1) **Java堆空间不足**:大量对象未被及时回收或内存泄漏;2) **线程栈空间不足**:递归过深或大量线程创建;3) **方法区溢出**:类信息过多,如CGLib代理类生成过多;4) **本机内存不足**:JNI调用消耗大量内存;5) **GC造成的内存不足**:频繁GC但效果不佳。解决方法包括调整JVM参数(如-Xmx、-Xss)、优化代码及使用高效垃圾回收器。
138 15
常见java OOM异常分析排查思路分析
|
25天前
|
Java
Java面试题之cpu占用率100%,进行定位和解决
这篇文章介绍了如何定位和解决Java服务中CPU占用率过高的问题,包括使用top命令找到高CPU占用的进程和线程,以及使用jstack工具获取堆栈信息来确定问题代码位置的步骤。
68 0
Java面试题之cpu占用率100%,进行定位和解决
|
2月前
|
缓存 JavaScript Java
常见java OOM异常分析排查思路分析
Java虚拟机(JVM)遇到 OutOfMemoryError(OOM)表示内存资源不足。常见OOM情况包括:1) **Java堆空间不足**:内存被大量对象占用且未及时回收,或内存泄漏;解决方法包括调整JVM堆内存大小、优化代码及修复内存泄漏。2) **线程栈空间不足**:单线程栈帧过大或频繁创建线程;可通过优化代码或调整-Xss参数解决。3) **方法区溢出**:运行时生成大量类导致方法区满载;需调整元空间大小或优化类加载机制。4) **本机内存不足**:JNI调用或内存泄漏引起;需检查并优化本机代码。5) **GC造成的内存不足**:频繁GC但效果不佳;需优化JVM参数、代码及垃圾回收器
常见java OOM异常分析排查思路分析
|
3月前
|
小程序 JavaScript Java
【Java】服务CPU占用率100%,教你用jstack排查定位
本文详细讲解如何使用jstack排查定位CPU高占用问题。首先介绍jstack的基本概念:它是诊断Java应用程序线程问题的工具,能生成线程堆栈快照,帮助找出程序中的瓶颈。接着,文章通过具体步骤演示如何使用`top`命令找到高CPU占用的Java进程及线程,再结合`jstack`命令获取堆栈信息并进行分析,最终定位问题代码。
253 1
【Java】服务CPU占用率100%,教你用jstack排查定位
|
4月前
|
监控 算法 Java
|
4月前
|
Java
Jstack 查看线程状态及定位占用 cpu 较高的 java 线程
Jstack 查看线程状态及定位占用 cpu 较高的 java 线程
547 2
|
3月前
|
存储 Java API
【Azure Developer】通过Azure提供的Azue Java JDK 查询虚拟机的CPU使用率和内存使用率
【Azure Developer】通过Azure提供的Azue Java JDK 查询虚拟机的CPU使用率和内存使用率
|
4月前
|
监控 算法 Java
压测分析Java内存和CPU暂用
7月更文挑战第7天
65 5
|
4月前
|
Java
手把手教你java CPU飙升300%如何优化
手把手教你java CPU飙升300%如何优化
56 0
|
Java BI Linux
从Java视角理解系统结构 (一) CPU上下文切换
本文是从Java视角理解系统结构连载文章 在高性能编程时,经常接触到多线程. 起初我们的理解是, 多个线程并行地执行总比单个线程要快, 就像多个人一起干活总比一个人干要快. 然而实际情况是, 多线程之间需要竞争IO设备, 或者竞争锁资源,导致往往执行速度还不如单个线程. 在这里有一个经常提及的概念就是: 上下文切换(Context Switch).
125 0
从Java视角理解系统结构 (一) CPU上下文切换