-XX:MaxDirectMemorySize

文章详细介绍了Java中的MaxDirectMemorySize参数,它是用于限制DirectByteBuffer分配的堆外内存的最大值。DirectByteBuffer是一种非堆内存,不被JVM的垃圾回收机制管理。通过设置-XX:MaxDirectMemorySize可以控制其大小,避免过度占用内存导致FullGC。同时,文章提到了BufferPool的概念,它是数据库系统中提高性能的缓冲区池,以及如何通过代码示例观察和管理DirectByteBuffer的使用情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-XX:MaxDirectMemorySize作用

用于设置直接内存的最大大小

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?

ByteBuffer 是 Java NIO(New I/O)库中的一种重要数据结构,专门设计用来高效地处理字节序列

ByteBuffer分类

1、heap ByteBuffer

一种是heap ByteBuffer,该类对象分配在JVM的堆内存里面,直接由Java虚拟机负责垃圾回收,

2、direct ByteBuffer

一种是direct ByteBuffer,是通过 jni 在虚拟机外内存中分配的。通过 jmap 无法查看该块内存的使用情况。只能通过 top 来看它的内存使用情况。

如何设置 direct ByteBuffer

direct ByteBuffer可以通过-XX:MaxDirectMemorySize来设置。默认大小等于-Xmx
用JDK8的一定要配置:-Xms -Xmx -XX:MaxDirectMemorySizeXmx + MaxDirectMemorySize的值不能超过docker的最大内存,不然docker内存占满了会被oomkill掉;
「引」JVM参数之MaxDirectMemorySize

什么是BufferPool?

Buffer Pool 主要用于提高数据访问的效率,通过在内存中缓存磁盘上的数据页,减少对物理磁盘的 I/O 操作次数,从而显著提升数据库系统的整体性能。

BufferPool 源码

// 提供对缓冲区使用情况信息的访问。
public interface BufferPool {
    String getName();
    long getCount();
    long getTotalCapacity();
    long getMemoryUsed();
}

// The management interface for a buffer pool
public interface BufferPoolMXBean extends PlatformManagedObject {	
// The name of this buffer pool
String getName();	

// An estimate of the number of buffers in this pool
long getCount();	

// An estimate of the total capacity of the buffers in this pool in bytes
long getTotalCapacity(); 

// An estimate of the memory that the JVM is using for this buffer pool in bytes, 
// or -1L if an estimate of the memory usage is not available
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();
    }
}

启动VM options

-Xmx200m -Xms50m -XX:+PrintCommandLineFlags 
--add-opens java.base/jdk.internal.misc=ALL-UNNAMED
--add-opens java.base/jdk.internal.access=ALL-UNNAMED

结果分析

-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 200M
java虚拟机已经从操作系统那里挖过来的内存   totalMemory : 50M
java虚拟机从操纵系统挖过来还没用上的内存   freeMemory : 45M

the maximum allocatable direct buffer memory: 200M

BufferPoolMXBean.Name: direct
BufferPoolMXBean.Count: 1
BufferPoolMXBean.TotalCapacity: 0M
BufferPoolMXBean.MemoryUsed: 0M

BufferPool.Name: direct
BufferPool.Count: 1
BufferPool.TotalCapacity: 0M
BufferPool.MemoryUsed: 0M
----------------------------------------------------------------------------
分配25M本地字节缓冲区 java.nio.DirectByteBuffer[pos=0 lim=26214400 cap=26214400]
创建10M对象 [B@5f4da5c3
----------------------------------------------------------------------------

java虚拟机从操纵系统那里挖到的最大的内存   maxMemory 200M
java虚拟机已经从操作系统那里挖过来的内存   totalMemory : 50M
java虚拟机从操纵系统挖过来还没用上的内存   freeMemory : 33M

the maximum allocatable direct buffer memory: 200M

BufferPoolMXBean.Name: direct
BufferPoolMXBean.Count: 2
BufferPoolMXBean.TotalCapacity: 25M
BufferPoolMXBean.MemoryUsed: 25M

BufferPool.Name: direct
BufferPool.Count: 2
BufferPool.TotalCapacity: 25M
BufferPool.MemoryUsed: 25M

----------------------------------------------------------------------------
分配25M本地字节缓冲区 java.nio.DirectByteBuffer[pos=0 lim=26214400 cap=26214400]
创建10M对象 [B@443b7951
----------------------------------------------------------------------------

java虚拟机从操纵系统那里挖到的最大的内存   maxMemory 200M
java虚拟机已经从操作系统那里挖过来的内存   totalMemory : 50M
java虚拟机从操纵系统挖过来还没用上的内存   freeMemory : 22M

the maximum allocatable direct buffer memory: 200M

BufferPoolMXBean.Name: direct
BufferPoolMXBean.Count: 3
BufferPoolMXBean.TotalCapacity: 50M
BufferPoolMXBean.MemoryUsed: 50M

BufferPool.Name: direct
BufferPool.Count: 3
BufferPool.TotalCapacity: 50M
BufferPool.MemoryUsed: 50M
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值