为什么 JVM 在我的测试程序之后有更多的空闲内存?

Why does the JVM have more free memory after my test program?

我做了一个测试程序来测试Runtime.freeMemory()方法。

public class RuntimeFreeMemory {

    public static void main(String[] args) {
        Runtime r = Runtime.getRuntime();
        System.out.println(r.freeMemory()); // 246939608

        String[] arr = new String[10000000];
        for (int i = 0; i < 10000000; i++)
            arr[i] = new String();

        System.out.println(r.freeMemory()); // 517655928
    }
}

当然,这些都是很大的数字,但我真的很想测试一下,因为像 10000 这样的数字不会削减它。但是当我 运行 它时,我得到了一些意想不到的数字。我认为最终可用内存会下降或与初始可用内存保持不变,但它们却超过了 double 初始可用内存。我 运行 这很多次,它总是围绕这些值。有人可以解释一下吗?

所报告的 freeMemory 可能受到 GC 的影响,并且由于您的数组分配导致堆已扩展。在开头和结尾打印 r.totalMemory 并进行比较可能会很有趣。

当 JVM 启动时,它实际上并没有预先分配(默认情况下)整个堆内存 - 它只是 "reserved" 和稍后 "committed" if/when 需要(在这一点上,堆已扩展)。

您可以尝试将 -Xms-Xmx 显式设置为相同的值,并且可能会获得更多预期结果。

例如通过使用 -Xms8g -Xmx8g 我得到以下信息:

    public static void main(String[] args) {
        Runtime r = Runtime.getRuntime();
        System.out.println(r.freeMemory()); // 8581851136
        System.out.println(r.totalMemory()); // 8589934592 

        System.out.println("Process PID: " + ProcessHandle.current().pid());

        String[] arr = new String[100000000];
        for (int i = 0; i < 100000000; i++)
            arr[i] = new String();

        System.out.println(r.freeMemory()); // 5717141504
        System.out.println(r.totalMemory()); // 8589934592
    }

    // compare results when using ONLY -Xmx8g
    // 537178112
    // 541065216
    // 3240407040
    // 6104809472

注意:使用-Xms仍然(通常)并不意味着内存驻留在RAM中: