7

当我使用 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

这是为什么?

4

2 回答 2

13

答案是:Java 11 的 GC(当显式调用时,例如 via 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();

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

于 2019-03-16T15:12:04.217 回答
2

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

于 2019-03-16T06:51:23.293 回答