面试官:内存泄漏,内存溢出如何排查?

在这里插入图片描述

前言

我们先来了解一下Java堆的组成机构。对于大多数应用来说,Java堆(Java Heap)是Java虚拟机锁管理的内存中最大的一块。Java堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存

堆的结构如下
在这里插入图片描述
新生代老年代的具体划分比例如下
在这里插入图片描述
分代的主要作用就是为了更高效的管理内存

内存泄漏和内存溢出是2个不同的概念

内存泄漏:对象已经不使用了,但是还占用着内存空间,没有被释放
内存溢出:堆空间不够用了,通常表现为OutOfMemoryError,内存泄漏通常会导致内存溢出

使用Java VisualVM远程分析堆

我们可以通过jdk自带的jvisualvm命令来分析堆的使用情况

我们写一个程序,来演示内存不断增加的场景

public class OomDemo {
    
    

    private static final int NUM = 1024;

    public static void main(String[] args) throws InterruptedException {
    
    
        List<byte[]> list = Lists.newArrayList();
        for (int i = 0; i < NUM; i++) {
    
    
            TimeUnit.SECONDS.sleep(1);
            list.add(new byte[NUM * NUM]);
        }
    }
}

在这里插入图片描述

命令行中执行jvisualvm即可弹出图形界面,我们可以连接到本机上的程序,也可以连接到远程机器,还可以分析生成快照文件等。

可以清晰的看到堆空间在不断上涨,用抽样器分析一下内存不断上涨的源头在哪里?
在这里插入图片描述
好家伙,byte数组居然占用了这么多内存

如果此时你还看不出程序哪里有问题,到监视这个Tab点击堆Dump这个按钮,会生成一个堆的快照,然后分析这个dump文件即可

在这里插入图片描述
byte数组实例很少,但是占用内存很多,再看一下具体的引用
在这里插入图片描述
可以看到在ArrayList中。

最后推荐一个插件Visual GC,可以清晰的看到堆的使用情况以垃圾收集信息。
点击工具选中插件即可
在这里插入图片描述

在这里插入图片描述
当然你可以通过jmap命令生成heapdump文件,然后用其他工具分析

Java虚拟机性能监控与故障处理工具

Java提供了很多实用命令供我们分析Java虚拟机的状态,如下面几个命令

jps:列出正在运行的虚拟机进程,并显示虚拟机执行主类

cis@mt002:~$ jps
70208 KmpService
183525 LinkAnalysisServer
25160 MipSerachServer

jmap(Memory Map for Java):命令用于生成堆转储快照(一般称为heapdump或dump文件)

在启动命令中配置如下参数,可以在OOM时生成快照,方便我们分析

-XX:+HeapDumpOnOutOfMemoryError

jstack(Stack Trace for Java):Java堆栈跟踪工具,生成虚拟机当前时刻的线程快照

可以用来分析线程死锁,死循环,线程长时间等待

参考博客

[1]https://blog.csdn.net/qq_35190492/article/details/105376377
内粗溢出的几种原因
[2]https://blog.csdn.net/cp_panda_5/article/details/79613870

猜你喜欢

转载自blog.csdn.net/zzti_erlie/article/details/114746000
今日推荐