java 直接内存溢出_JVM学习笔记——本机直接内存溢出

一、JVM直接内存

直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可以使用 native 函数库直接分配堆外内存,然后通过一个存储在Java堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。

本机直接内存的分配不会受到Java 堆大小的限制,受到本机总内存大小限制

直接内存也可以由 -XX:MaxDirectMemorySize 指定

直接内存申请空间耗费更高的性能

直接内存IO读写的性能要优于普通的堆内存

当我们的需要频繁访问大的内存而不是申请和释放空间时,通过使用直接内存可以提高性能。

二、直接内存溢出测试

测试代码如下,运行时添加参数 -Xmx20M -XX:MaxDirectMemorySize=10M 设置降低直接内存的空间来加快异常的抛出

package test_DirectMemoryOOM;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class DirectrMemoryOOM {

private static final int _1M = 1024 * 1024;

public static void main(String[] args) throws Exception {

Field unsafeField = Unsafe.class.getDeclaredFields()[0];

unsafeField.setAccessible(true);

@SuppressWarnings("restriction")

Unsafe unsafe = (Unsafe) unsafeField.get(null);

while(true) {

unsafe.allocateMemory(_1M);

}

}

}

对于在eclipse上,使用sun.misc.Unsafe会出现找不到类的报错,这是出于安全考虑做的限制。可以通过以下方法解决:

Project > properties > Java Compilee > Errors/Warnings :

69221d305141

eclipse配置.png

运行结果:

Exception in thread "main" java.lang.OutOfMemoryError

at sun.misc.Unsafe.allocateMemory(Native Method)

at test_DirectMemoryOOM.DirectrMemoryOOM.main(DirectrMemoryOOM.java:15)

不断申请1M的空间,最终会耗尽内存抛出 OutOfMemoryError 异常。

三、注意

由于申请直接内存不由虚拟机管理,所以由此导致的 OOM 是不会在 Heap Dump 文件中看出明显的异常。当 OOM 后发现 Dump 文件很小同时程序直接或间接使用了 NIO ,就可以考虑一下这方面的原因。

关于 Heap Dump 的内容可以在 JVM学习笔记——jhat的使用 了解

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值