准备

具体步骤

命令行使用 jmap

image.png

使用JvisualVM

捕获的heap dump文件是一个临时文件,关闭JVisualVM后自动删除,若要保留,需要将其另存为文件。可通过以下方法捕获heap dump:
在左侧“Application”(应用程序)子窗口中右击相应的应用程序,选择Heap Dump(堆Dump)。
在Monitor(监视)子标签页中点击Heap Dump(堆Dump)按钮。本地应用程序的Heap dumps作为应用程序标签页的一个子标签页打开。同时,heap dump在左侧的Application(应用程序)栏中对应一个含有时间戳的节点。
右击这个节点选择save as(另存为)即可将heap dump保存到本地。

使用MAT打开Dump文件

打开后,我们就可以看到有哪些可以作为GC Roots的对象
image.png
里面我们能够看到有一些常用的Java类,然后Thread线程。

JProfiler的GC Roots溯源

我们在实际的开发中,一般不会查找全部的GC Roots,可能只是查找某个对象的整个链路,或者称为GC Roots溯源,这个时候,我们就可以使用JProfiler
image.png

判断造成OOM原因

当我们程序出现OOM的时候,我们就需要进行排查,我们首先使用下面的例子进行说明

  1. /**
  2. * 内存溢出排查
  3. * -Xms8m -Xmx8m -XX:HeapDumpOnOutOfMemoryError
  4. */
  5. public class HeapOOM {
  6. // 创建1M的文件
  7. byte [] buffer = new byte[1 * 1024 * 1024];
  8. public static void main(String[] args) {
  9. ArrayList<HeapOOM> list = new ArrayList<>();
  10. int count = 0;
  11. try {
  12. while (true) {
  13. list.add(new HeapOOM());
  14. count++;
  15. }
  16. } catch (Exception e) {
  17. e.getStackTrace();
  18. System.out.println("count:" + count);
  19. }
  20. }
  21. }

上述代码就是不断的创建一个1M小字节数组,然后让内存溢出,我们需要限制一下内存大小,同时使用HeapDumpOnOutOfMemoryError将出错时候的dump文件输出

  1. -Xms8m -Xmx8m -XX:HeapDumpOnOutOfMemoryError

我们将生成的dump文件打开,然后点击Biggest Objects就能够看到超大对象
image.png
然后我们通过线程,还能够定位到哪里出现OOM
image.png