有没有处理过内存泄漏问题?是如何定位的?

内存泄漏是一种内在病源,其外在症状可能包括:

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

严重的内存泄漏通常会伴随频繁的Full GC,因此在分析和排查内存泄漏问题时,首先需要查看Full GC情况。以下是主要的操作步骤:

1)使用jps命令查看正在运行的Java进程ID。

2)使用top -p [pid]命令查看进程的CPU和内存使用情况。

3)使用top -Hp [pid]命令查看进程下所有线程的CPU和内存情况。

4)将线程ID转换为16进制:printf "%x\n" [pid],输出的值即为线程栈信息中的nid。

例如:printf "%x\n" 29471,输出为731f。

5)抓取线程栈:jstack 29452 > 29452.txt,可以多次抓取以进行比较。

在线程栈信息中查找对应线程号的16进制值,以下是线程信息示例。可以使用VisualVM插件TDA进行线程栈分析。

"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007fbe2c164000 nid=0x731f runnable [0x0000000000000000]
  java.lang.Thread.State: RUNNABLE

6)使用jstat -gcutil [pid] 5000 10命令每隔5秒输出GC信息,输出10次,查看YGC和Full GC的次数。通常情况下,YGC要么不增加,要么增加缓慢,而Full GC会迅速增加。

或者使用jstat -gccause [pid] 5000命令输出GC摘要信息。

或者使用jmap -heap [pid]命令查看堆的摘要信息,关注老年代内存使用是否达到阈值,如果达到阈值,就会执行Full GC。

7)如果发现Full GC的次数过多,很有可能存在内存泄漏。

8)使用jmap -histo:live [pid]命令输出每个类的对象数量、内存大小(以字节为单位)和完整类名。

9)生成dump文件,并借助工具分析具有大量对象的位置。

使用jmap生成dump文件的示例:

# jmap -dump:live,format=b,file=29471.dump 29471
Dumping heap to /root/dump ...
Heap dump file created

10)对dump文件进行

分析。

可以使用jhat命令进行分析:jhat -port 8000 29471.dump,然后在浏览器中访问jhat服务,端口为8000。

通常可以使用图形化工具进行分析,如JDK自带的jvisualvm,从菜单中选择文件 -> 载入dump文件。

也可以使用第三方工具进行分析,如JProfiler和GCViewer。Eclipse IDE也提供了MAT工具进行分析,还可以使用在线分析平台GCEasy。

请注意,如果dump文件较大,则分析过程可能会占用较大内存。

11)在dump文件分析结果中查找存在大量对象的位置,并查看对这些对象的引用。

通过以上步骤,基本上可以定位到代码层面的逻辑问题。

标签: java, Java面试题, Java问题合集, Java编程, Java问题精选, Java常见问题