jvm 内存溢出-直接内存溢出

雨点打透心脏的1/2处 2022-03-01 03:38 521阅读 0赞

jvm 内存溢出-直接内存溢出

DirectMemory 容量可通过 -XX:MaxDirectMemorySize 指定,如果不指定,则默认与 Java 堆最大值( -Xmx 指定)一样,下面程序利用 DirectByteBuffe 模拟直接内存溢出的情况

  1. import java.nio.ByteBuffer;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class DirectBufferOom {
  5. public static void main(String[] args) {
  6. final int _1M = 1024 * 1024;
  7. List<ByteBuffer> buffers = new ArrayList<>();
  8. int count = 1;
  9. while (true) {
  10. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1M);
  11. buffers.add(byteBuffer);
  12. System.out.println(count++);
  13. }
  14. }
  15. }

在命令行运行 java -XX:MaxDirectMemorySize=10M DirectBufferOom ,很快控制台就会出现异常

  1. Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
  2. at java.nio.Bits.reserveMemory(Bits.java:695)
  3. at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
  4. at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
  5. at DirectBufferOom.main(DirectBufferOom.java:12)

其实它并没有真正向操作系统申请分配内存,而是通过计算得知内存无法分配,于是手动抛出异常。下面的程序利用 Unsafe 类模拟直接内存溢出

  1. import sun.misc.Unsafe;
  2. import java.lang.reflect.Field;
  3. public class UnsafeOom {
  4. private static final int _1M = 1024 * 1024;
  5. public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
  6. Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
  7. unsafeField.setAccessible(true);
  8. Unsafe unsafe = (Unsafe) unsafeField.get(null);
  9. while (true) {
  10. unsafe.allocateMemory(_1M);
  11. }
  12. }
  13. }

在命令行运行 java -XX:MaxDirectMemorySize=10M UnsafeOom ,结果如下

  1. Exception in thread"main"java.lang.OutOfMemoryError
  2. at sun.misc.Unsafe.allocateMemoryNative Method
  3. at org.fenixsoft.oom.DMOOM.mainDMOOM.java20

由 DirectMemory 导致的内存溢出,一个明显的特征是在 Heap Dump 文件中不会看见明显的异常,如果读者发现 OOM 之后 Dump 文件很小,而程序中又直接或间接使用了 NIO ,那就可以考虑检查一下是不是这方面的原因。

发表评论

表情:
评论列表 (有 0 条评论,521人围观)

还没有评论,来说两句吧...

相关阅读

    相关 实现jvm内存溢出

    那么我们如何来构建一个堆内存溢出呢?其实很简单,我们只要定义一个`List`对象,然后通过一个循环不停的往`List`里面塞对象。因为只要Controller不被回收,那么它里

    相关 JVM内存溢出详解

    JVM内存溢出详解(栈溢出,堆溢出,持久代溢出以及无法创建本地线程) 写在前面 内存溢出和内存泄漏的区别: 内存溢出 out of memory,是指程序在申请内存