关于OOM的一些理解

发布时间 2023-05-23 11:07:21作者: rockdow
import java.io.IOException;
import java.util.ArrayList;

public class TestOOM {
    private static final int _8MB = 8 * 1024 * 1024;

    // -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc -XX:-ScavengeBeforeFullGC
    public static void main(String[] args) throws InterruptedException, IOException {
        new Thread(() -> {
            ArrayList<byte[]> list = new ArrayList<>();
            list.add(new byte[_8MB]);
            list.add(new byte[_8MB]);
        }).start();

        Thread.sleep(2000);
    }
}

在上述程序中,设置了堆内存为20M,其中新生代区占10M(伊甸园区占8M,from和to平分余下的2M),老年代占10M,结果如下:

子线程连续申请了两个8M的字节数组,导致堆内存溢出,但是主线程依然可以运行,当然肯定会受到堆空间不足的影响。

可以看到老年代中仍存放有子线程第一次申请的8M字节数组,GC并没有因为子线程导致堆内存溢出而回收其占用的堆空间,这是由于Java的垃圾回收机制是依靠可达性算法,而不是线程的生命周期,发生堆溢出时第一次申请的8M字节数组仍然是可达的。