NIO 堆外内存
您目前处于:技术核心竞争力  2016-09-25

Java 内存模型

堆外内存 / 直接内存(Direct Memory)

JDK1.4 中引入的NIO类,基于 channel 和 Buffer 的 I/O 方式,可用 Native 库直接分配堆外内存,然后利用一个存储在堆中的 DirectByteBuffer 对象作为这块内存引用来操作。避免了在 Java 堆 和Native 堆中来回复制数据。


直接内存并不是虚拟机运行时数据区的一部分也不是 Java 虚拟机规范中定义的内存区域及内存溢出。

优点:

1. 堆外内存不影响 JVM GC,程序会减少 Full GC。

2. IO 操作使用堆外内存比堆内存快。因为堆内在flush到远程时,会先复制到直接内存(非堆内存),然后在发送;直接移到堆外就更快了

缺点:

1. 堆外内存难以控制,如果内存泄漏,那么很难排查

2. 堆外内存只能通过序列化和反序列化来存储,保存对象速度比堆内存慢,不适合存储很复杂的对象。一般简单的对象或者扁平化的比较适合。

常用场景:

通常用在通信过程中做缓冲池,在 mina,netty 等 NIO 框架中屡见不鲜。

堆外内存导致的内存泄露

Java 可以通过 java.nio.ByteBuffer.allocateDirect(capacity) 直接使用 non java heap(Java堆外)的内存 。

使用目的:

1. 开辟数据缓冲区

2. 可以突破 JVM 内存限制,操作更多的物理内存

使用问题:

通过 ByteBuffer.allocateDirect() 使用的内存不能够通过 JVM 相关内存工具 VisualVM 等查看 heap 的内存占用,所以内存泄露也较难查找。

使用 Java heap(Java 堆)分配内存,可以直接通过工具查看出内存占用

java.nio.ByteBuffer.allocate(capacity)

使用 non Java heap(非 Java 堆)通过操作系统直接分配内存,会导致查看不出 Java heap 的内存占用,导致泄露看不出来会导致查看不出 Java heap 的内存占用,导致泄露看不出来

java.nio.ByteBuffer.allocateDirect(capacity)

转载请并标注: “本文转载自 linkedkeeper.com ”  ©著作权归作者所有