为什么 System.gc() 并行时 RSS 没有减少,而 G1 却减少了?

问题描述 投票:0回答:1

我正在使用 Java 17。我有一个 2GB 的容器并运行以下 Java 程序:

import java.util.*;

public class Main{
        public static Map<byte[], byte[]> m = new HashMap<>();

        public static void main(String args[]) throws Exception {
                int i = 0;
                while(true){
                        i++;
                        byte b[] = new byte[1024 * 1024];
                        m.put(b, b);
                        if(i % 700 == 0){
                                System.out.println("Reached limit: " + i);
                                m = new HashMap<>();
                                Thread.sleep(500000);
                                System.gc();
                                Thread.sleep(500000);
                        }
                }
        }
}

使用选项运行它

java -XX:+UseParallelGC \
     -XX:InitialRAMPercentage=40 \
     -XX:MaxRAMPercentage=40 \
     -XX:-ShrinkHeapInSteps \
     -XX:MinHeapFreeRatio=10 \
     -XX:MaxHeapFreeRatio=10 Main

我不断收到堆

pmap
报告的RSS为800MB,并且没有变低。

     Address Perm   Offset Device   Inode    Size    Rss    Pss Referenced Anonymous 
    ccc00000 rw-p 00000000  00:00       0  839680 838812 838812     838812    838812       

但很明显

System.gc()
已被应用并且未被忽略:

[5.871s][info ][gc             ] GC(4) Pause Full (System.gc()) 702M->1M(792M) 2.820ms

所以

-XX:-ShrinkHeapInSteps -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=10 -XX:+UseParallelGC
System.gc()
都不会减少RSS。

我需要减少 RSS,因为大多数时候 Java 堆一定很小,而且白白消耗这么多 RSS 效率很低。

值得注意的是,

System.gc()
可以减少G1 GC的RSS量并按预期工作。

有没有办法做到并行,为什么 G1 需要

System.gc()
和简单的完整 GC 还不够?

java memory-management jvm garbage-collection g1gc
1个回答
0
投票

并行 GC 永远不会取消提交为 Java 堆保留的内存,而 G1 可能会取消提交未使用的内存(即将其返回给操作系统)。在 JDK 12 之前,G1 仅在完整 GC 或并发循环后才能返回内存。从 JDK 12 开始,它可以更频繁地取消提交 - 有关详细信息,请参阅 JEP 346

另请参阅:Java 进程的内存占用

© www.soinside.com 2019 - 2024. All rights reserved.