jvm 内存溢出-直接内存溢出
jvm 内存溢出-直接内存溢出
DirectMemory 容量可通过 -XX:MaxDirectMemorySize
指定,如果不指定,则默认与 Java 堆最大值( -Xmx
指定)一样,下面程序利用 DirectByteBuffe 模拟直接内存溢出的情况
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class DirectBufferOom {
public static void main(String[] args) {
final int _1M = 1024 * 1024;
List<ByteBuffer> buffers = new ArrayList<>();
int count = 1;
while (true) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(_1M);
buffers.add(byteBuffer);
System.out.println(count++);
}
}
}
在命令行运行 java -XX:MaxDirectMemorySize=10M DirectBufferOom
,很快控制台就会出现异常
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:695)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at DirectBufferOom.main(DirectBufferOom.java:12)
其实它并没有真正向操作系统申请分配内存,而是通过计算得知内存无法分配,于是手动抛出异常。下面的程序利用 Unsafe
类模拟直接内存溢出
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class UnsafeOom {
private static final int _1M = 1024 * 1024;
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while (true) {
unsafe.allocateMemory(_1M);
}
}
}
在命令行运行 java -XX:MaxDirectMemorySize=10M UnsafeOom
,结果如下
Exception in thread"main"java.lang.OutOfMemoryError
at sun.misc.Unsafe.allocateMemory(Native Method)
at org.fenixsoft.oom.DMOOM.main(DMOOM.java:20)
由 DirectMemory 导致的内存溢出,一个明显的特征是在 Heap Dump 文件中不会看见明显的异常,如果读者发现 OOM 之后 Dump 文件很小,而程序中又直接或间接使用了 NIO ,那就可以考虑检查一下是不是这方面的原因。
还没有评论,来说两句吧...