Direct buffer memory溢出分析
描述 | Oracle jdk的Direct Byte Buffers由专属的一块内存区域管理控制,所有 Direct Byte Buffer 大小的总和不能超过限制。达到限制后,只有在释放足够的旧缓冲区以提供足够的空间来分配新缓冲区时,才能分配新的直接字节缓冲区。如果这一块内存区域配置不当就会影响到系统的正常运行。 |
分析 | - 查看发现问题时的日志
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory at java.nio.Bits.reserveMemory(Bits.java:694) at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123) at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311) |
- 从上面日志可以发现在系统运行过程中出现了内存溢出
- 这种溢出跟heap 内存溢出不同,并不会产生heapdump文件
- 目前的虚拟机参数配置为 -Xmx4096m
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/heap - DirectBuffers requested by the method called java.nio.ByteBuffer.allocateDirect() are allocated in C-Heap and not in Java heap,默认分配在c堆,不在heap区域(JVM Error Message "java.lang.OutOfMemoryError: Direct buffer memory"
(Doc ID 1493911.1) ) - DirectBuffers 默认大小由Runtime.getRuntime.maxMemory()
决定,(Doc ID 1493911.1) |
解决 | 通过上面的分析可以找到解决措施, - 如果没有直接指定DirectBuffers内存大小,这块内存受heap堆分配决定,因为Runtime.getRuntime.maxMemory()由jvm参数 -Xmx决定
- 举个例子如果-Xmx4g,那么DirectBuffers大小在3.7g上下
- 根据官方的解释如下
-XX:MaxDirectMemorySize=size Sets the maximum total size (in bytes) of the New I/O (the java.nio package) direct-buffer allocations. Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, g or G to indicate gigabytes. By default, the size is set to 0, meaning that the JVM chooses the size for NIO direct-buffer allocations automatically. The following examples illustrate how to set the NIO size to 1024 KB in different units: -XX:MaxDirectMemorySize=1m -XX:MaxDirectMemorySize=1024k -XX:MaxDirectMemorySize=1048576 通过此参数可以分配更多的内存以保证需要 - 测试验证:直接配置为1g后,即使-Xmx设置为256m,也可以分配500m的direct buffer
In the following example we set the MaxDirectMemorySize to 1 GB which is enough to allocate a DirectBuffer of 500 MB size. The OutOfMemory error does not occur anymore even if we set -Xmx to 256 MB only. Example: $ java -XX:MaxDirectMemorySize=1g -Xmx256m <APP_NAME> 238616576 $ cat <APP_NAME>.java public class Dibu { public static void main(String[] args) { java.nio.ByteBuffer.allocateDirect(500*1024*1024); // 500 MB System.out.println(Runtime.getRuntime().maxMemory()); } } |
- 更新后重启虚拟机生效
|
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。