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

7xzttuei  于 2024-01-07  发布在  其他
关注(0)|答案(1)|浏览(297)

我使用的是Java 17。我有一个容量为2GB的容器,并运行以下Java程序:

  1. import java.util.*;
  2. public class Main{
  3. public static Map<byte[], byte[]> m = new HashMap<>();
  4. public static void main(String args[]) throws Exception {
  5. int i = 0;
  6. while(true){
  7. i++;
  8. byte b[] = new byte[1024 * 1024];
  9. m.put(b, b);
  10. if(i % 700 == 0){
  11. System.out.println("Reached limit: " + i);
  12. m = new HashMap<>();
  13. Thread.sleep(500000);
  14. System.gc();
  15. Thread.sleep(500000);
  16. }
  17. }
  18. }
  19. }

字符串
使用选项运行它

  1. java -XX:+UseParallelGC \
  2. -XX:InitialRAMPercentage=40 \
  3. -XX:MaxRAMPercentage=40 \
  4. -XX:-ShrinkHeapInSteps \
  5. -XX:MinHeapFreeRatio=10 \
  6. -XX:MaxHeapFreeRatio=10 Main


我一直收到pmap报告的堆的RSS是800MB,它没有变得更低。

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


但很明显,System.gc()是应用的,而不是忽略的:

  1. [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

相关问题