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

7xzttuei  于 4个月前  发布在  其他
关注(0)|答案(1)|浏览(51)

我使用的是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:+UseParallelGCSystem.gc()都不能使RSS约化。
我需要减少RSS,因为大多数时候Java堆必须很小,而且白白消耗这么多RSS是效率低下的。
值得注意的是,System.gc()可以减少G1 GC的RSS量,并按预期工作。
有没有一种方法可以在并行环境中做到这一点?为什么G1需要System.gc(),而仅仅是完全GC是不够的?

flmtquvp

flmtquvp1#

并行GC从不取消为Java Heap保留的内存,而G1可以取消未使用的内存(即将其返回给操作系统)。在JDK 12之前,G1只能在完整的GC或并发周期之后返回内存。自JDK 12以来,它可以更频繁地取消提交-有关详细信息,请参阅JEP 346
标签:Memory footprint of a Java process

相关问题