当前位置: 首页 > 图灵资讯 > java面试题> JVM高频面试题-有没有处理过内存溢出(OOM)问题?是如何定位的?

JVM高频面试题-有没有处理过内存溢出(OOM)问题?是如何定位的?

来源:图灵教育
时间:2023-11-13 09:18:16
 

有没有处理过内存溢出(OOM)问题?是如何定位的?

内存泄漏是内在病源,外在病症表现可能有:

  • 应用程序长时间连续运行时性能严重下降
  • CPU 使用率飙升,甚至到 100%
  • 频繁 Full GC,各种报警,例如接口超时报警等
  • 应用程序抛出 OutOfMemoryError 错误
  • 应用程序偶尔会耗尽连接对象

严重内存泄漏往往伴随频繁的 Full GC,所以分析排查内存泄漏问题首先还得从查看 Full GC 入手。主要有以下操作步骤:

  1. 使用 jps 查看运行的 Java 进程 ID
  2. 使用top -p [pid] 查看进程使用 CPU 和 MEM 的情况
  3. 使用 top -Hp [pid] 查看进程下的所有线程占 CPU 和 MEM 的情况
  4. 将线程 ID 转换为 16 进制:printf "%x\n" [pid],输出的值就是线程栈信息中的 nid。例如:printf "%x\n" 29471,换行输出 731f
  5. 抓取线程栈:jstack 29452 > 29452.txt,可以多抓几次做个对比。在线程栈信息中找到对应线程号的 16 进制值,如下是 731f 线程的信息。线程栈分析可使用 Visualvm 插件 TDA
"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007fbe2c164000 nid=0x731f runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
  1. 使用jstat -gcutil [pid] 5000 10 每隔 5 秒输出 GC 信息,输出 10 次,查看 YGCFull GC 次数。通常会出现 YGC 不增加或增加缓慢,而 Full GC 增加很快。或使用 jstat -gccause [pid] 5000 ,同样是输出 GC 摘要信息。或使用 jmap -heap [pid] 查看堆的摘要信息,关注老年代内存使用是否达到阀值,若达到阀值就会执行 Full GC。
  2. 如果发现 Full GC 次数太多,就很大概率存在内存泄漏了
  3. 使用 jmap -histo:live [pid] 输出每个类的对象数量,内存大小(字节单位)及全限定类名。
  4. 生成 dump 文件,借助工具分析哪 个对象非常多,基本就能定位到问题在那了使用 jmap 生成 dump 文件:
# jmap -dump:live,format=b,file=29471.dump 29471
Dumping heap to /root/dump ...
Heap dump file created

可以使用 jhat 命令分析:jhat -port 8000 29471.dump,浏览器访问 jhat 服务,端口是 8000。通常使用图形化工具分析,如 JDK 自带的 jvisualvm,从菜单 > 文件 > 装入 dump 文件。或使用第三方式具分析的,如 JProfiler 也是个图形化工具,GCViewer 工具。Eclipse 或以使用 MAT 工具查看。或使用在线分析平台 GCEasy。注意:如果 dump 文件较大的话,分析会占比较大的内存。基本上就可以定位到代码层的逻辑了。

    1. 在 dump 文析结果中查找存在大量的对象,再查对其的引用。
    2. dump 文件分析