英文:
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 < 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't actually allocate (by default) whole heap memory upfront - it's just "reserved" and later "committed" 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("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
Note: Using `-Xms` still doesn't (usually) mean that the memory is resident in RAM: https://stackoverflow.com/questions/48982636/java-heap-xms-and-linux-free-memory-different
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论