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

Why is OpenJDK 11 Java garbage collector *decreasing* free memory in this sample program?

当我使用 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());
    }
}

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

Free memory before garbage collection: 266881496
Free memory  after garbage collection: 7772200

当我 运行 使用 Oracle 的 Java 8 时,这不会发生:

Free memory before garbage collection: 254741016
Free memory  after garbage collection: 255795064

这是为什么?

我认为您看到的是 JDK 决定您的堆对于您的应用程序的需求来说太大了,并将它的块返回给操作系统,从而减少了您的 Java 堆大小作为副作用还有 free/unused 堆内存。

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

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

"free memory"是Java进程占用的内存,目前没有使用。因此,如果您执行垃圾收集并且 Java 占用的内存减少,则可用内存量也会减少。

因此,计算 Java 进程的 "free memory" 的常用方法是使用

Runtime r = Runtime.getRuntime();
long free = r.maxMemory() - r.totalMemory() + r.freeMemory();

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