java nio 堆外内存_NIO 堆外内存
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)
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)