我使用的是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是不够的?
1条答案
按热度按时间flmtquvp1#
并行GC从不取消为Java Heap保留的内存,而G1可以取消未使用的内存(即将其返回给操作系统)。在JDK 12之前,G1只能在完整的GC或并发周期之后返回内存。自JDK 12以来,它可以更频繁地取消提交-有关详细信息,请参阅JEP 346。
标签:Memory footprint of a Java process