首页 > 解决方案 > Runtime.getRuntime().maxMemory() 计算方法

问题描述

这是代码:

    System.out.println("Runtime max: " + mb(Runtime.getRuntime().maxMemory()));
    MemoryMXBean m = ManagementFactory.getMemoryMXBean();

    System.out.println("Non-heap: " + mb(m.getNonHeapMemoryUsage().getMax()));
    System.out.println("Heap: " + mb(m.getHeapMemoryUsage().getMax()));

    for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) {
        System.out.println("Pool: " + mp.getName() +
                " (type " + mp.getType() + ")" +
                " = " + mb(mp.getUsage().getMax()));
    }  

在JDK8上运行代码是:

    [root@docker-runner-2486794196-0fzm0 docker-runner]# java -version
    java版本“1.8.0_181”
    Java(TM) SE 运行时环境 (build 1.8.0_181-b13)
    Java HotSpot(TM) 64 位服务器 VM(内部版本 25.181-b13,混合模式)
    [root@docker-runner-2486794196-0fzm0 docker-runner]# java -jar -Xmx1024M -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap test.jar
    最大运行时间:954728448 (910.50 M)
    非堆:-1 (-0.00 M)
    堆:954728448 (910.50 M)
    池:代码缓存(类型非堆内存)= 251658240 (240.00 M)
    池:元空间(类型非堆内存)= -1 (-0.00 M)
    池:压缩类空间(类型非堆内存)= 1073741824 (1024.00 M)
    池:PS Eden Space(堆内存类型)= 355467264 (339.00 M)
    池:PS Survivor Space(堆内存类型)= 1048576 (1.00 M)
    池:PS Old Gen(堆内存类型)= 716177408 (683.00 M)
    

*最大运行时间:954728448 (910.50 M) *

Runtime.maxMemory 是 910.50M,我想知道这是怎么回事

在JDK7上, "Runtime.getRuntime().maxMemory()" = "-Xmx" - "Survivor" ,但是在JDK8上不行。</p>

标签: java-8jvmjvm-hotspot

解决方案


在 JDK 8 中,公式Runtime.maxMemory() = Xmx - Survivor仍然是公平的,但诀窍在于如何估计 Survivor。

您尚未设置初始堆大小 ( -Xms),并且默认情况下自适应大小策略处于启用状态。这意味着堆可以调整大小并且堆生成边界可以在运行时移动。Runtime.maxMemory()保守地估计内存量,从 New Generation 的大小中减去最大可能的幸存者大小。

Runtime.maxMemory() = OldGen + NewGen - MaxSurvivor

  where MaxSurvivor = NewGen / MinSurvivorRatio

在您的示例中,默认情况下 OldGen = 683 MB、NewGen = 341 MB 和 MinSurvivorRatio = 3。那是,

Runtime.maxMemory() = 683 + 341 - (341/3) = 910.333 MB

如果您禁用-XX:-UseAdaptiveSizePolicy或将初始堆大小设置-Xms为与 相同的值-Xmx,您将再次看到Runtime.maxMemory() = OldGen + Eden + Survivor.


推荐阅读