下面是 《深入理解 Java 虚拟机 第三版》2.2.7 小节 关于 Java 直接内存的描述。
DirectMemoryReporter { private static final String BUSINESS_KEY = "netty_direct_memory"; private AtomicLong directMemory PlatformDependent.class,"DIRECT_MEMORY_COUNTER"); field.setAccessible(true); try{ directMemory } } public void doReport(String processName){ try{ long memoryInb = directMemory.get
DirectMemory 容量可通过 -XX:MaxDirectMemorySize 指定,如果不指定,则默认与 Java 堆最大值(-Xmx 指定)一样,以下代码中越过了 DirectByteBuffer while (true) { unsafe.allocateMemory(_1Mb); } } } 运行结果: image.png 由 DirectMemory
. // private static long directMemory = 64 * 1024 * 1024; // Returns the maximum amount of allocatable direct buffer memory. // The directMemory variable is initialized during system initialization the saveAndRemoveProperties method. // public static long maxDirectMemory() { return directMemory ); } else { long l = Long.parseLong(s); if (l > -1) directMemory 的值;而VM的maxDirectMemory方法则返回的是directMemory的值 获取maxDirectMemory的值 实例 public BufferPoolMXBean getDirectBufferPoolMBean
//private static long directMemory = 64 * 1024 * 1024;// Returns the maximum amount of allocatable direct buffer memory.// The directMemory variable is initialized during system initialization// in the saveAndRemoveProperties //public static long maxDirectMemory() { return directMemory;} 这里directMemory默认赋值为64MB,那对外内存的默认大小是 if (s.equals("-1")) { // -XX:MaxDirectMemorySize not given, take default directMemory ); } else { long l = Long.parseLong(s); if (l > -1) directMemory
Off-Heap [JVM 堆外内存]1、DirectMemory1.1. 通过自定义系统参数进行修改:-Dtaskmanager.memory.managed.size=xxMB3.Task Off-Heap内存此块内存默认配置值是0,一般不需要用户手动去调整,如果用户的代码程序里用到了 DirectMemory ,或者依赖了第三方框架例如 Pulsar, Netty,对 DirectMemory 有需求,那么用户需要手动指定这块内存的大小,不然容易出现的 java.lang.OutOfMemoryError:
本机直接内存溢出 DirectMemory容量通过-XX:MaxDirectMemorySize指定,如果不指定,默认与Java堆最大值(-Xmx)一致。 由DirectMemory导致的内存溢出,在Heap Dump文件中不会看到明显异常,如果发现OOM之后Dump文件很小,而程序中又直接或间接使用了NIO,可以考虑这方面原因。
设置栈大小的方法是设置-Xss参数 3.PermGen space 第三个异常是关于perm的异常内容,我们需要的是设置方法区的大小,实现方式是通过设置-XX:PermSize和-XX:MaxPermSize参数 4.DirectMemory 第四个异常估计遇到的人就不多了,是DirectMemory内存相关的 DirectMemoruSize可以通过设置 -XX:MaxDirectMemorySize参数指定容量大小,如果不指定的话,那么就跟堆的最大值一致
而今天的主角内存溢出,按之前《JVM进阶调优系列(2)JVM内存区域怎么划分,分别有什么用》说的那样,内存溢出会发生在heap堆内存、Metaspace元数据区、stack栈内存溢出、直接内存DirectMemory 五、DirectMemory直接内存溢出 在JVM堆内存之外,除了有虚拟机栈内存、元数据区,还有一个DirectMemory直接内存区。这个区域的作用是什么呢? ByteBuffer.allocateDirect(2 * 1024 * 1024); directMemList.add(directMem2Mb); } }}5.2 DirectMemory 5.3 DirectMemory直接内存溢出原因分析 直接内存的应用,常见的就是NIO,比如Netty框架。
原因:SeaTunnel底层网络通信基于Netty,大量使用堆外内存(DirectMemory)来零拷贝传输数据。 展开代码语言:BashAI代码解释-Xmx2560m#2.5G给堆#剩余1.5G留给堆外内存(Netty)+操作系统内核+其他进程原理:SeaTunnel底层使用Netty进行网络通信,会大量申请堆外内存(DirectMemory 剩下的30%需要留给:堆外内存(DirectMemory):SeaTunnel/Netty传输数据使用。Metaspace:类元数据。ThreadStacks:每个线程占用1MB(默认)。
问题四:nio框架占用DirectMemory导致的OutOfMemoryError 处理方式:使用XX:+DisableExplicitGC 增加DirectMemory的大小; 1、DirectMemory 5、GC仅在Java堆被填满,以至于无法为堆分配请求提供服务时发生,或者在Java应用程序中显示调用System.gc()函数来释放内存(一些NIO框架就是用这个方法释放占用的DirectMemory)
代码中maxMemory = VM.maxDirectMemory(); private static long directMemory = 64 * 1024 * 1024; //64MB public static long maxDirectMemory() { return directMemory; } 实际上在 JVM启动时,会对System做初始化,实际上堆外内存的大小设置逻辑为 Dsun.nio.MaxDirectMemorySize指定了这个属性,只要它不等于-1,那效果和加了-XX:MaxDirectMemorySize一样的,如果两个参数都没指定,那么最大堆外内存的值来自于directMemory
四、本机直接内存溢出 DirectMemory容量可通过-XX:MaxDirectMemorySize指定,如果不指定,默认与Java堆最大值一样。 sun.misc.Unsafe.allocateMemory(Native Method) at com.sandy.jvm.chapter02.DirectMemoryOOM.main(DirectMemoryOOM.java:22) 由DirectMemory
的引用,降低remark时的开销-----一般CMS的GC耗时 80%都在remark阶段 -XX:+CMSScavengeBeforeRemark jmap分析: 问题四:nio框架占用DirectMemory 导致的OutOfMemoryError 处理方式:使用XX:+DisableExplicitGC 增加DirectMemory的大小; 1、DirectMemory不属于java堆内存、分配内存其实是调用操作系统的 5、GC仅在Java堆被填满,以至于无法为堆分配请求提供服务时发生,或者在Java应用程序中显示调用System.gc()函数来释放内存(一些NIO框架就是用这个方法释放占用的DirectMemory)
DirectByteBuffer ByteBuffer buffer = ByteBuffer.allocateDirect(int capacity); 这里的DirectByteBuffer分配使用的内存空间就是前面的DirectMemory allocateDirect的源码: 以上源码其实就干了四件事: 计算分配大小,至少是一个内存页pagesize的大小 记录剩余可分配的direct memory大小 用Unsafe的JNI实际分配DirectMemory Heap原本应该存储对象的实际数据,而对于DirectByteBuffer,DirectByteBuffer里面只存储了一个基地址address,它指向了堆外内存真正存储数据的DirectMemory。
DirectMemory Out Of Memory DirectMemory容量可通过-XX:MaxDirectMemorySize指定,如果不指定,则默认与Java堆最大值(-Xmx指定)一样,下面的代码直接通过反射获取 sun.misc.Unsafe.allocateMemory(Native Method) at org.fenixsoft.oom.DMOOM.main(DMOOM.java:20) 由DirectMemory
at com.fdd.test.StackOutOfMemoryError.go(StackOutOfMemoryError.java:13)*/ 3、方法区和运行时常量池溢出 4、本机直接内存溢出 DirectMemory
而dubbo出于规避netty的一个bug // 因ChannelFactory的关闭有DirectMemory泄露, // 采用静态化规避 https://issues.jboss.org/browse
直接内存DirectMemory大小设置-intsmaze 直接内存DirectMemory的大小默认为 -Xmx 的JVM堆的最大值,但是并不受其限制(理论上说受限于进程的虚拟地址空间大小,比如 32 位的windows上,每个进程有4G的虚拟空间除去 2G为OS内核保留外,再减去 JVM堆的最大值,剩余的才是DirectMemory大小。)
但是如果用户没有设置正确的DirectMemory的大小,Bookie将会收到OutOfDirectMemory的异常。 在4.9.0版本中,BookKeeper引入智能的内存管理,绝大部分时间使用DirectMemory,在DirectMemory不够用的情况下,BookKeeper会使用堆内的内存。