JAVA 线上故障排查完整套路,java面试刷题网站

使用 jstack 分析 CPU 问题

我们先用 ps 命令找到对应进程的 pid(如果你有好几个目标进程,可以先用 top 看一下哪个占用比较高)。

接着用top -H -p pid来找到 CPU 使用率比较高的一些线程

JAVA 线上故障排查完整套路

然后将占用最高的 pid 转换为 16 进制printf ‘%x\n’ pid得到 nid

JAVA 线上故障排查完整套路

接着直接在 jstack 中找到相应的堆栈信息jstack pid |grep ‘nid’ -C5 –color

JAVA 线上故障排查完整套路

可以看到我们已经找到了 nid 为 0x42 的堆栈信息,接着只要仔细分析一番即可。

当然更常见的是我们对整个 jstack 文件进行分析,通常我们会比较关注 WAITING 和 TIMED_WAITING 的部分,BLOCKED 就不用说了。我们可以使用命令cat jstack.log | grep “java.lang.Thread.State” | sort -nr | uniq -c来对 jstack 的状态有一个整体的把握,如果 WAITING 之类的特别多,那么多半是有问题啦。

JAVA 线上故障排查完整套路

频繁 gc

当然我们还是会使用 jstack 来分析问题,但有时候我们可以先确定下 gc 是不是太频繁,使用jstat -gc pid 1000命令来对 gc 分代变化情况进行观察,1000 表示采样间隔(ms),S0C/S1C、S0U/S1U、EC/EU、OC/OU、MC/MU 分别代表两个 Survivor 区、Eden 区、老年代、元数据区的容量和使用量。YGC/YGT、FGC/FGCT、GCT 则代表 YoungGc、FullGc 的耗时和次数以及总耗时。如果看到 gc 比较频繁,再针对 gc 方面做进一步分析,具体可以参考一下 gc 章节的描述。

JAVA 线上故障排查完整套路

上下文切换

针对频繁上下文问题,我们可以使用vmstat命令来进行查看

JAVA 线上故障排查完整套路

cs(context switch)一列则代表了上下文切换的次数。

如果我们希望对特定的 pid 进行监控那么可以使用 pidstat -w pid命令,cswch 和 nvcswch 表示自愿及非自愿切换。

JAVA 线上故障排查完整套路

磁盘

==

磁盘问题和 CPU 一样是属于比较基础的。首先是磁盘空间方面,我们直接使用df -hl来查看文件系统状态

JAVA 线上故障排查完整套路

更多时候,磁盘问题还是性能上的问题。我们可以通过 iostatiostat -d -k -x来进行分析

JAVA 线上故障排查完整套路

最后一列%util可以看到每块磁盘写入的程度,而rrqpm/s以及wrqm/s分别表示读写速度,一般就能帮助定位到具体哪块磁盘出现问题了。

另外我们还需要知道是哪个进程在进行读写,一般来说开发自己心里有数,或者用 iotop 命令来进行定位文件读写的来源。

JAVA 线上故障排查完整套路

不过这边拿到的是 tid,我们要转换成 pid,可以通过 readlink 来找到 pidreadlink -f /proc/*/task/tid/…/…。

JAVA 线上故障排查完整套路

找到 pid 之后就可以看这个进程具体的读写情况cat /proc/pid/io

JAVA 线上故障排查完整套路

我们还可以通过 lsof 命令来确定具体的文件读写情况lsof -p pid

JAVA 线上故障排查完整套路

内存

======

内存问题排查起来相对比 CPU 麻烦一些,场景也比较多。主要包括 OOM、GC 问题和堆外内存。一般来讲,我们会先用free命令先来检查一发内存的各种情况。

JAVA 线上故障排查完整套路

堆内内存

内存问题大多还都是堆内内存问题。表象上主要分为 OOM 和 Stack Overflo。

OOM

JMV 中的内存不足,OOM 大致可以分为以下几种:

Exception in thread “main” java.lang.OutOfMemoryError: unable to create new native thread

这个意思是没有足够的内存空间给线程分配 Java 栈,基本上还是线程池代码写的有问题,比如说忘记 shutdown,所以说应该首先从代码层面来寻找问题,使用 jstack 或者 jmap。如果一切都正常,JVM 方面可以通过指定Xss来减少单个 thread stack 的大小。另外也可以在系统层面,可以通过修改

/etc/security/limits.confnofile 和 nproc 来增大 os 对线程的限制

JAVA 线上故障排查完整套路

Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

这个意思是堆的内存占用已经达到-Xmx 设置的最大值,应该是最常见的 OOM 错误了。解决思路仍然是先应该在代码中找,怀疑存在内存泄漏,通过 jstack 和 jmap 去定位问题。如果说一切都正常,才需要通过调整Xmx的值来扩大内存。

Caused by: java.lang.OutOfMemoryError: Meta space

这个意思是元数据区的内存占用已经达到XX:MaxMetaspaceSize设置的最大值,排查思路和上面的一致,参数方面可以通过XX:MaxPermSize来进行调整(这里就不说 1.8 以前的永久代了)。

Stack Overflow

栈内存溢出,这个大家见到也比较多。

Exception in thread “main” java.lang.StackOverflowError

表示线程栈需要的内存大于 Xss 值,同样也是先进行排查,参数方面通过Xss来调整,但调整的太大可能又会引起 OOM。

使用 JMAP 定位代码内存泄漏

上述关于 OOM 和 Stack Overflo 的代码排查方面,我们一般使用 JMAPjmap -dump:format=b,file=filename pid来导出 dump 文件

JAVA 线上故障排查完整套路

通过 mat(Eclipse Memory Analysis Tools)导入 dump 文件进行分析,内存泄漏问题一般我们直接选 Leak Suspects 即可,mat 给出了内存泄漏的建议。另外也可以选择 Top Consumers 来查看最大对象报告。和线程相关的问题可以选择 thread overview 进行分析。除此之外就是选择 Histogram 类概览来自己慢慢分析,大家可以搜搜 mat 的相关教程。

JAVA 线上故障排查完整套路

日常开发中,代码产生内存泄漏是比较常见的事,并且比较隐蔽,需要开发者更加关注细节。比如说每次请求都 new 对象,导致大量重复创建对象;进行文件流操作但未正确关闭;手动不当触发 gc;ByteBuffer 缓存分配不合理等都会造成代码 OOM。

另一方面,我们可以在启动参数中指定-XX:+

HeapDumpOnOutOfMemoryError来保存 OOM 时的 dump 文件。

gc 问题和线程

gc 问题除了影响 CPU 也会影响内存,排查思路也是一致的。一般先使用 jstat 来查看分代变化情况,比如 youngGC 或者 fullGC 次数是不是太多呀;EU、OU 等指标增长是不是异常呀等。

线程的话太多而且不被及时 gc 也会引发 oom,大部分就是之前说的unable to create new native thread。除了 jstack 细细分析 dump 文件外,我们一般先会看下总体线程,通过pstreee -p pid |wc -l。

JAVA 线上故障排查完整套路

或者直接通过查看/proc/pid/task的数量即为线程数量。

JAVA 线上故障排查完整套路

堆外内存

如果碰到堆外内存溢出,那可真是太不幸了。首先堆外内存溢出表现就是物理常驻内存增长快,报错的话视使用方式都不确定,如果由于使用 Netty 导致的,那错误日志里可能会出现OutOfDirectMemoryError错误,如果直接是 DirectByteBuffer,那会报OutOfMemoryError: Direct buffer memory。

堆外内存溢出往往是和 NIO 的使用相关,一般我们先通过 pmap 来查看下进程占用的内存情况pmap -x pid | sort -rn -k3 | head -30,这段意思是查看对应 pid 倒序前 30 大的内存段。这边可以再一段时间后再跑一次命令看看内存增长情况,或者和正常机器比较可疑的内存段在哪里。

JAVA 线上故障排查完整套路

我们如果确定有可疑的内存端,需要通过 gdb 来分析gdb --batch --pid {pid} -ex “dump memory filename.dump {内存起始地址} {内存起始地址+内存块大小}”

JAVA 线上故障排查完整套路

获取 dump 文件后可用 heaxdump 进行查看hexdump -C filename | less,不过大多数看到的都是二进制乱码。

NMT 是 Java7U40 引入的 HotSpot 新特性,配合 jcmd 命令我们就可以看到具体内存组成了。需要在启动参数中加入 -XX:NativeMemoryTracking=summary 或者 -XX:NativeMemoryTracking=detail,会有略微性能损耗。

一般对于堆外内存缓慢增长直到爆炸的情况来说,可以先设一个基线jcmd pid VM.native_memory baseline。

JAVA 线上故障排查完整套路

然后等放一段时间后再去看看内存增长的情况,通过jcmd pid VM.native_memory detail.diff(summary.diff)做一下 summary 或者 detail 级别的 diff。

JAVA 线上故障排查完整套路

JAVA 线上故障排查完整套路

可以看到 jcmd 分析出来的内存十分详细,包括堆内、线程以及 gc(所以上述其他内存异常其实都可以用 nmt 来分析),这边堆外内存我们重点关注 Internal 的内存增长,如果增长十分明显的话那就是有问题了。

detail 级别的话还会有具体内存段的增长情况,如下图。

JAVA 线上故障排查完整套路

此外在系统层面,我们还可以使用 strace 命令来监控内存分配 strace -f -e “brk,mmap,munmap” -p pid

这边内存分配信息主要包括了 pid 和内存地址。

JAVA 线上故障排查完整套路

不过其实上面那些操作也很难定位到具体的问题点,关键还是要看错误日志栈,找到可疑的对象,搞清楚它的回收机制,然后去分析对应的对象。比如 DirectByteBuffer 分配内存的话,是需要 full GC 或者手动 system.gc 来进行回收的(所以最好不要使用-XX:+DisableExplicitGC)。那么其实我们可以跟踪一下 DirectByteBuffer 对象的内存情况,通过jmap -histo:live pid手动触发 fullGC 来看看堆外内存有没有被回收。如果被回收了,那么大概率是堆外内存本身分配的太小了,通过-XX:MaxDirectMemorySize进行调整。如果没有什么变化,那就要使用 jmap 去分析那些不能被 gc 的对象,以及和 DirectByteBuffer 之间的引用关系了。

GC 问题

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

总结

如果你选择了IT行业并坚定的走下去,这个方向肯定是没有一丝问题的,这是个高薪行业,但是高薪是凭自己的努力学习获取来的,这次我把P8大佬用过的一些学习笔记(pdf)都整理在本文中了

《Java中高级核心知识全面解析》

小米商场项目实战,别再担心面试没有实战项目:

将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频**

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-34j7USOg-1710967004955)]

总结

如果你选择了IT行业并坚定的走下去,这个方向肯定是没有一丝问题的,这是个高薪行业,但是高薪是凭自己的努力学习获取来的,这次我把P8大佬用过的一些学习笔记(pdf)都整理在本文中了

《Java中高级核心知识全面解析》

[外链图片转存中…(img-h5GO6lRP-1710967004955)]

小米商场项目实战,别再担心面试没有实战项目:

[外链图片转存中…(img-LcVHijP7-1710967004956)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 14
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值