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

huangapple go评论79阅读模式
英文:

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这样的数字是不够的。但是当我运行它时,我得到了一些意料之外的数字。我原以为最终的剩余内存会减少或保持与初始剩余内存相当,但实际上它们超过了初始剩余内存的两倍。我多次运行了这个程序,结果总是在这些值左右波动。有人可以解释一下这是怎么回事吗?

英文:

I made a test program to test the Runtime.freeMemory() method.

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 &lt; 10000000; i++)
			arr[i] = new String();
		
		System.out.println(r.freeMemory()); // 517655928
	}
}

Of course, these are big numbers, but I really wanted to test it as numbers like 10000 wouldn't cut it. But when I ran it, I got some unexpected numbers. I thought the end free memory would go down or stay somewhat the same as the initial free memory, but instead they went over double what the initial free memory was. I ran this multiple times and it was always something around these values. Can somebody explain this?

答案1

得分: 1

`freeMemory`报告的数值可能会受到垃圾回收的影响,以及由于数组分配而导致堆扩展的影响。在开始和结束时打印`r.totalMemory`并进行比较可能会很有趣。

当JVM启动时,它实际上并不会(默认情况下)提前分配整个堆内存 - 它只是被“保留”,如果/当需要时才“提交”(在这一点上,堆被扩展)。

您可以尝试将`-Xms`和`-Xmx`设置为相同的值,可能会得到更符合预期的结果。

例如,通过使用`-Xms8g -Xmx8g`,我得到了以下结果:
```java
    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
    }

    // 仅使用 -Xmx8g 时进行结果比较
    // 537178112
    // 541065216
    // 3240407040
    // 6104809472

注意:使用-Xms仍然通常不意味着内存驻留在RAM中:https://stackoverflow.com/questions/48982636/java-heap-xms-and-linux-free-memory-different


<details>
<summary>英文:</summary>

The `freeMemory` reported may be affected by GC and by the fact that the heap has been expanded because of your array allocations. It might be interesting to also print `r.totalMemory` at the beginning and at the end and compare.

When the JVM starts, it doesn&#39;t actually allocate (by default) whole heap memory upfront - it&#39;s just &quot;reserved&quot; and later &quot;committed&quot; if/when needed (at that point, heap is expanded).

You can try to set `-Xms` and `-Xmx` explicitly to the same value and will likely get more expected results.

E.g. by using `-Xms8g -Xmx8g` I got following:
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(&quot;Process PID: &quot; + ProcessHandle.current().pid());
    
    String[] arr = new String[100000000];
    for (int i = 0; i &lt; 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

Note: Using `-Xms` still doesn&#39;t (usually) mean that the memory is resident in RAM: https://stackoverflow.com/questions/48982636/java-heap-xms-and-linux-free-memory-different

</details>



huangapple
  • 本文由 发表于 2020年4月7日 08:27:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/61070966.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定