JVM OOM问题排查与解决思路

OOM原因

1. 堆溢出

报错信息:

java.lang.OutOfMemoryError: Java heap space

  1. 代码中可能存在大对象分配,无法获得足够的内存分配

  2. 可能发生内存泄露,导致内存被无效占用以至于耗尽

2. 永久代/元空间溢出

报错信息:

java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: Metaspace

  1. 在Java7之前,频繁的使用String.intern()方法

  2. 代码中存在大量的反射操作,导致方法区被撑爆,无法卸载

3. 方法栈溢出

报错信息:

java.lang.OutOfMemoryError : unable to create new native Thread

每个 Java 线程都需要占用一定的内存空间,当 JVM 向底层操作系统请求创建一个新的 native 线程时,如果没有足够的资源分配就会报此类错误。出现这种异常,基本上都是创建的了大量的线程导致的。

4. swap溢出

报错信息 :

java.lang.OutOfMemoryError: Out of swap space

这种情况一般是操作系统导致的,可能的原因有:

  1. swap 分区大小分配不足;

  2. 其他进程消耗了所有的内存。

5. 本地方法溢出

报错信息 :

java.lang.OutOfMemoryError: stack_trace_with_native_method

本地方法在运行时出现了内存分配失败,和之前的方法栈溢出不同,方法栈溢出发生在 JVM 代码层面,而本地方法溢出发生在JNI代码或本地方法处。

6. GC overhead limit exceeded

报错信息:

java.lang.OutOfMemoryError:GC overhead limit exceeded

超过98%的时间用来做GC并且回收了不到2%的堆内存时会抛出此异常。

  1. 项目中可能有大量的死循环或有使用大内存的代码
  2. 存在内存泄露

7. Requested array size exceeds VM limit

报错信息:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

JVM 限制了数组的最大长度,该错误表示程序请求创建的数组超过最大长度限制。

8. Direct buffer memory

报错信息:

java.lang.OutOfMemoryError: Direct buffer memory

Direct ByteBuffer 的默认大小为 64 MB,一旦使用超出限制,就会抛出此错误。

JVM监控工具介绍

1. jps命令

显示指定系统内所有的java虚拟机系统

  • -l:输出进程ID和应用主类的完整路径;
  • -v:输出向jvm传递的参数,此处展示为idea中显式配置的VM-options参数,其他内容自行查看即可;
  • -m:输出向main方法传递的参数,服务启动前可以在idea的Program-arguments配置;

2. jinfo命令

查看和调整虚拟机参数。在命令后面带pid进程号,可以输出指定进程的配置信息。

  • -sysprops:输出 Java System Properties 参数;
  • -flags:输出 VM Flags 参数;

3. jstat命令

输出JVM的监控指标

  • -gc:输出java堆相关信息;
  • -gcutil:输出java堆各个区域使用百分比;

4. jstack命令

输出指定进程当前时刻在JVM中的线程信息

5. jmap命令

输出指定进程的内存中对象映射信息,或者堆的关键信息、内存的使用统计、GC算法、配置、类的实例信息及内存占用等

  • -heap:输出java堆详细信息;
  • -dump:输出java堆内存快照;

6. jconsole

Java内置的JVM性能监控工具,在熟悉上述的命令行工具之后,对于该可视化工具的使用不会太陌生,在命令中可以查看到的默认参数或者应用自定义配置,在该工具中也可以找到,并且以图形化的方式呈现;

7. jvisualvm

VisualVM 提供了一个可视界面,用于查看JVM上运行的基于 Java 技术的应用程序的详细信息。可以查看本地应用程序或远程主机上运行的应用程序的相关数据。此外,还可以捕获有关 JVM 软件实例的数据,并将该数据保存到本地系统,以供后期查看或与其他用户共享。

通过jvisualvm定位OOM问题

获取dump文件

注意导出文件占用内存很大的时候,可能会导不出来

  • 方式一:提前配置jvm参数,在系统挂了后会在指定目录下生成dump文件

    -XX:+HeapDumpOnOutOfMemoryError

    -XX:HeapDumpPath=./ (导出路径)

  • 方式二:使用命令行导出

    jmap -dump:format=b,file=demo.hprof pid

通过jvisualvm工具装载dump文件

查看内存占用最高的业务对象,并找到GCRoot并查看线程栈从而定位问题
在这里插入图片描述
在这里插入图片描述

通过Arthas工具定位问题

执行如下命令下载arthas-boot.jar,再用java -jar命令启动:

wgethttps://arthas.aliyun.com/arthas-boot.jar; java-jararthas-boot.jar

arthas-boot是Arthas的启动程序,它启动后,会列出所有的Java进程,用户可以选择需要诊断的目标进程。

使用dashboard 命令可以查看当前系统的实时数据面板。可以查看到CPU、内存、GC、运行环境等信息。
在这里插入图片描述

使用 sc 命令来查找JVM里已加载的类,通过-d参数,可以打印出类加载的具体信息,很方便查找类加载问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值