为什么此示例程序中的OpenJDK 11 Java垃圾收集器“减少”了可用内存?

use*_*967 7 java garbage-collection azul-zulu java-11

当我使用OpenJDK 11(在Windows 10上为Zulu发行版)编译并运行以下非常简单的Java程序时:

public class GCTest {
    public static void main(String[] args) {
        System.out.println("Free memory before garbage collection: " + Runtime.getRuntime().freeMemory());
        Runtime.getRuntime().gc();
        System.out.println("Free memory  after garbage collection: " + Runtime.getRuntime().freeMemory());
    }
}
Run Code Online (Sandbox Code Playgroud)

看起来垃圾回收正在减少可用内存量:

Free memory before garbage collection: 266881496
Free memory  after garbage collection: 7772200
Run Code Online (Sandbox Code Playgroud)

当我使用Oracle Java 8运行它时,不会发生这种情况:

Free memory before garbage collection: 254741016
Free memory  after garbage collection: 255795064
Run Code Online (Sandbox Code Playgroud)

这是为什么?

Rob*_*ert 12

答案是:Java 11的GC(显式调用时,例如通过System.gc())可以减少Java进程(在Java中称为totalMemory)的已用内存。

在Java 8中,默认的垃圾回收器无法减少Java进程的已用内存。Java进程占用的内存从未被释放。仅当您切换到G1GC垃圾回收器(选项'-XX:+UseG1GC')时,Java 8才能减少Java进程的已用内存(如果您手动调用System.gc())。

“空闲内存”是Java进程占用的内存,但当前未使用。因此,如果执行垃圾回收并且减少了Java占用的内存,那么可用内存的数量也会减少。

因此,计算Java进程的“可用内存”的常用方法是使用

Runtime r = Runtime.getRuntime();
long free = r.maxMemory() - r.totalMemory() + r.freeMemory();
Run Code Online (Sandbox Code Playgroud)

这种方式与Java进程当前占用的内存无关。