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