一个Java报出OutOfMemory引发的血案

目录

一个生产的OOM


一个生产的OOM

1.生产报了一个异常,java.lang.OutOfMemoryError: Java heap space,如下

每次操作能复现。初看像是堆内存溢出了。所以决定dump出来看看

跟踪操作

查看jvm进程

ps -ef | grep java

拿到pid号4447

生成dump文件

切换到root用户:sudo su-

jmap -dump:live,format=b,file=test_heap.bin 4447

会生成dump文件:test_heap.bin.然后通过跳板机jumpserver从服务器上down下来

分析dump文件

分析dump文件有几种方式

  • jhat命令。以我的为例,把dump文件放到window的盘下面,打开cmd,运行命令接着访问 http://localhost:7001/,就可以分析对应的实例关系。
  • VisualVM。大家试过就会发现,上面一种方式,查看起来不是很方便,可以利用Jdk自带的图形化工具VisualVM。

发现char[]占比已经85%了,然后就可以分析它的引用关系,可能还要根据代码检查,需要一定的时间与经验。

后面发现是一个循环里面的不断的生成StringBuffer变量sb,导致最后sb.append的字符越来越长,最终导致oom。后来修改了业务逻辑,没再出过对应的异常了

所以,在此,记录并总结下,这类问题一般的应对方法(个人经验哈,不保证绝对正确,不代表方法最佳)。

Jdk自带的命令

Jps  (JVM Process Status Tools)

用于查看正在运行的虚拟机进程以及对应的ID,对应本机来说和PID相同(类似ps -ef | grep jav)

OptionFunction
-q只输出LVMID
-m输出JVM启动时传给主类的方法
-l输出主类的全名,如果是Jar则输出jar的路径
-v输出JVM的启动参数

Jmap (JVM Memory Map for Java)

上面例子,用到了jmap生成堆转储快照

jmap -dump:live,format=b,file=test_heap.bin 4447

查看一下帮助

除了生成堆转储外,还有一个很重要的用途是查看堆信息

 jmap -heap 22220

jmap的作用不仅仅是为了获取dump文件,还可以用于查询finalize执行队列、Java堆和永久带的详细信息,如空间使用率、垃圾回收器等。

OptionFunction
-dump生成对应的dump信息,用法为-dump:[live,]format=b,file={fileName}
-finalizerinfo显示在F-Queue中等待的Finalizer方法的对象(只在linux下生效)
-heap显示堆的详细信息、垃圾回收器信息、参数配置、分代详情等
-histo显示堆栈中的对象的统计信息,包含类、实例数量和合计容量

-permstat

-F

以ClassLoder为统计口径显示永久带的内存状态

当虚拟机对-dump无响应时可使用这个选项强制生成dump快照

Jinfo (JVM configuration Info for Java)

Jinfo的作用是实时查看虚拟机的各项参数信息jps –v可以查看虚拟机在启动时被显式指定的参数信息,但是如果你想知道默认的一些参数信息呢?除了去查询对应的资料以外,jinfo就显得很重要了

Jstat(JVM Statistics Monitoring Tools)

jstat主要用于监控虚拟机的各种运行状态信息,如类的装载、内存、垃圾回收、JIT编译器等

可以监控gc的状况:第3秒钟输出一次gc的状态,连续查10次

OptionFunction
-gc监视Java堆,包含eden、2个survivor区、old区和永久带区域的容量、已用空间、GC时间合计等信息
-gccapcity监视内容与-gc相同,但输出主要关注Java区域用到的最大和最小空间
-gcutil监视内容与-gc相同,但输出主要关注已使用空间占总空间的百分比
-gccause与-gcutil输出信息相同,额外输出导致上次GC产生的原因
-gcnew监控新生代的GC情况
-gcnewcapacity与-gcnew监控信息相同,输出主要关注使用到的最大和最小空间
-gcold监控老生代的GC情况
-gcoldcapacity与-gcold监控信息相同,输出主要关注使用到的最大和最小空间
-gcpermcapacity输出永久带用到的最大和最小空间
-compiler输出JIT编译器编译过的方法、耗时信息
-printcompilation输出已经被JIT编译的方法
-class监视类的装载、卸载数量以及类的装载总空间和耗费时间等

Jhat (JVM Heap Analysis Tool)

jhat是用来分析dump文件的一个微型的HTTP/HTML服务器,它能将生成的dump文件生成在线的HTML文件,让我们可以通过浏览器进行查阅

然而实际中我们很少使用这个工具,因为一般服务器上设置的堆、栈内存都比较大,生成的dump也比较大,直接用jhat容易造成内存溢出,而是我们大部分会将对应的文件拷贝下来,通过其他可视化的工具进行分析。

Jstack(JVM Stack Trace for java)

jstack用于JVM当前时刻的线程快照,又称threaddump文件,它是JVM当前每一条线程正在执行的堆栈信息的集合。看下用法,如下图

再看下当前进程的情况

生成线程快照的主要目的是为了定位线程出现长时间停顿的原因,如线程死锁、死循环、请求外部时长过长导致线程停顿的原因。通过jstack我们就可以知道哪些进程在后台做些什么?在等待什么资源等!

OptionFunction
-F当正常输出的请求不响应时强制输出线程堆栈
-l除堆栈信息外,显示关于锁的附加信息
-m显示native方法的堆栈信息

获取dump文件的几种方式

  • jmap命令 
    jmap -dump:live,format=b,file=test_heap.bin 4447
  • 配置参数 在JVM的配置参数中可以添加 -XX:+HeapDumpOnOutOfMemoryError 参数,当应用抛出 OutOfMemoryError 时自动生成dump文件;
  • Linux环境下还可以使用kill -3 pid恐吓JVM生成dump文件

参与资料:Jvm监控工具

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值