-XX:MaxDirectMemorySize
最大堆外内存大小,此参数的含义是当Direct ByteBuffer分配的堆外内存到达指定大小后就触发Full GC
。 首先可以在jdk文档中找到:关于MaxDirectMemorySize内存的描述: 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 参考 关于JDK8中最大堆外内存大小MaxDirectMemorySize
ByteBuffer(字节缓冲区)分类
heap ByteBuffer -> -XX:Xmx 一种是heap ByteBuffer,该类对象分配在JVM的堆内存里面,直接由Java虚拟机负责垃圾回收, direct ByteBuffer -> -XX:MaxDirectMemorySize 一种是direct ByteBuffer是通过jni在虚拟机外内存中分配的。通过jmap无法查看该快内存的使用情况。只能通过top来看它的内存使用情况。 JVM堆内存大小可以通过-Xmx
来设置 direct ByteBuffer可以通过-XX:MaxDirectMemorySize
来设置 没有配置MaxDirectMemorySize的,默认MaxDirectMemorySize的大小即等于-Xmx 用JDK8的一定要配置:-Xms -Xmx -XX:MaxDirectMemorySize
,【Xmx + MaxDirectMemorySize】的值不能超过docker的最大内存,不然docker内存占满了会被oomkill掉; 参考 JVM参数之MaxDirectMemorySize
启动VM options
- Xmx200m
- Xms50m
- XX : + PrintCommandLineFlags
-- add- opens java. base / jdk. internal. misc= ALL - UNNAMED
-- add- opens java. base / jdk. internal. access= ALL - UNNAMED
背景了解
public interface BufferPool { String getName ( ) ; long getCount ( ) ; long getTotalCapacity ( ) ; long getMemoryUsed ( ) ;
}
public interface BufferPoolMXBean extends PlatformManagedObject {
String getName ( ) ;
long getCount ( ) ;
long getTotalCapacity ( ) ;
long getMemoryUsed ( ) ;
练习代码
public class MaxDirectMemorySize { public static void main ( String [ ] args) { printJVMRuntime ( ) ; printDirectMemory ( ) ; System . out. println ( "分配25M本地字节缓冲区 " + ByteBuffer . allocateDirect ( 25 * 1024 * 1024 ) ) ; System . out. println ( "创建10M对象 " + new byte [ 10 * 1024 * 1024 ] ) ; printJVMRuntime ( ) ; printDirectMemory ( ) ; System . out. println ( "分配25M本地字节缓冲区 " + ByteBuffer . allocateDirect ( 25 * 1024 * 1024 ) ) ; System . out. println ( "创建10M对象 " + new byte [ 10 * 1024 * 1024 ] ) ; printJVMRuntime ( ) ; printDirectMemory ( ) ; } private static void printJVMRuntime ( ) { System . out. println ( "java虚拟机从操纵系统那里挖到的最大的内存 maxMemory " + Runtime . getRuntime ( ) . maxMemory ( ) / 1024 / 1024 + "M" ) ; System . out. println ( "java虚拟机已经从操作系统那里挖过来的内存 totalMemory : " + Runtime . getRuntime ( ) . totalMemory ( ) / 1024 / 1024 + "M" ) ; System . out. println ( "java虚拟机从操纵系统挖过来还没用上的内存 freeMemory : " + Runtime . getRuntime ( ) . freeMemory ( ) / 1024 / 1024 + "M" ) ; } private static void printDirectMemory ( ) { System . out. println ( "the maximum allocatable direct buffer memory: " + VM . maxDirectMemory ( ) / 1024 / 1024 + "M" ) ; System . out. println ( "BufferPoolMXBean.Name: " + getDirectBufferPoolMBean ( ) . getName ( ) ) ; System . out. println ( "BufferPoolMXBean.Count: " + getDirectBufferPoolMBean ( ) . getCount ( ) ) ; System . out. println ( "BufferPoolMXBean.TotalCapacity: " + getDirectBufferPoolMBean ( ) . getTotalCapacity ( ) / 1024 / 1024 + "M" ) ; System . out. println ( "BufferPoolMXBean.MemoryUsed: " + getDirectBufferPoolMBean ( ) . getMemoryUsed ( ) / 1024 / 1024 + "M" ) ; System . out. println ( "BufferPool.Name: " + getNioBufferPool ( ) . getName ( ) ) ; System . out. println ( "BufferPool.Count: " + getNioBufferPool ( ) . getCount ( ) ) ; System . out. println ( "BufferPool.TotalCapacity: " + getNioBufferPool ( ) . getTotalCapacity ( ) / 1024 / 1024 + "M" ) ; System . out. println ( "BufferPool.MemoryUsed: " + getNioBufferPool ( ) . getMemoryUsed ( ) / 1024 / 1024 + "M" ) ; } public static BufferPoolMXBean getDirectBufferPoolMBean ( ) { return ManagementFactory . getPlatformMXBeans ( BufferPoolMXBean . class ) . stream ( ) . filter ( e -> e. getName ( ) . equals ( "direct" ) ) . findFirst ( ) . orElseThrow ( ) ; } public static VM. BufferPool getNioBufferPool ( ) { return SharedSecrets . getJavaNioAccess ( ) . getDirectBufferPool ( ) ; }
}
结果分析
-XX:ConcGCThreads=3 -XX:G1ConcRefinementThreads=13 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=52428800
-XX:MarkStackSize=4194304 -XX:MaxHeapSize=209715200
-XX:MinHeapSize=52428800 -XX:+PrintCommandLineFlags
-XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
java虚拟机从操纵系统那里挖到的最大的内存 maxMemory 200 M
java虚拟机已经从操作系统那里挖过来的内存 totalMemory : 50 M
java虚拟机从操纵系统挖过来还没用上的内存 freeMemory : 45 Mthe maximum allocatable direct buffer memory: 200 MBufferPoolMXBean. Name : direct
BufferPoolMXBean. Count : 1
BufferPoolMXBean. TotalCapacity : 0 M
BufferPoolMXBean. MemoryUsed : 0 MBufferPool. Name : direct
BufferPool. Count : 1
BufferPool. TotalCapacity : 0 M
BufferPool. MemoryUsed : 0 M分配25 M本地字节缓冲区 java. nio. DirectByteBuffer[ pos= 0 lim= 26214400 cap= 26214400 ]
创建10 M对象 [ B @5f4da5c3 java虚拟机从操纵系统那里挖到的最大的内存 maxMemory 200 M
java虚拟机已经从操作系统那里挖过来的内存 totalMemory : 50 M
java虚拟机从操纵系统挖过来还没用上的内存 freeMemory : 33 Mthe maximum allocatable direct buffer memory: 200 MBufferPoolMXBean. Name : direct
BufferPoolMXBean. Count : 2
BufferPoolMXBean. TotalCapacity : 25 M
BufferPoolMXBean. MemoryUsed : 25 MBufferPool. Name : direct
BufferPool. Count : 2
BufferPool. TotalCapacity : 25 M
BufferPool. MemoryUsed : 25 M分配25 M本地字节缓冲区 java. nio. DirectByteBuffer[ pos= 0 lim= 26214400 cap= 26214400 ]
创建10 M对象 [ B @443b7951 java虚拟机从操纵系统那里挖到的最大的内存 maxMemory 200 M
java虚拟机已经从操作系统那里挖过来的内存 totalMemory : 50 M
java虚拟机从操纵系统挖过来还没用上的内存 freeMemory : 22 Mthe maximum allocatable direct buffer memory: 200 MBufferPoolMXBean. Name : direct
BufferPoolMXBean. Count : 3
BufferPoolMXBean. TotalCapacity : 50 M
BufferPoolMXBean. MemoryUsed : 50 MBufferPool. Name : direct
BufferPool. Count : 3
BufferPool. TotalCapacity : 50 M
BufferPool. MemoryUsed : 50 M