java - ZGC最大堆大小超过物理内存

标签 java jvm-arguments

  1. JVM 选项是
-server -Xmx100g -Xms100g -XX:MaxMetaspaceSize=1G -Xss512k 
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:MaxGCPauseMillis=30 
-XX:ConcGCThreads=4 -XX:ParallelGCThreads=12 
-XX:+DisableExplicitGC -XX:LargePageSizeInBytes=128m
  • 内存为256G
  •              total       used       free     shared    buffers     cached
    Mem:           251        250          1        100          0        138
    -/+ buffers/cache:        112        139
    Swap:            7          0          7
    
    
  • top命令显示进程的RES为303G
  •    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                           
    240731 xxx       20   0 17.0t 302g 297g S  6.6 119.9 256:35.43 java
    
  • jvm 配置文件显示如下
  • ./jhsdb jmap --heap --pid 240731
    Attaching to process ID 240731, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 11.0.2+9
    
    using thread-local object allocation.
    ZGC with 12 thread(s)
    
    Heap Configuration:
       MinHeapFreeRatio         = 40
       MaxHeapFreeRatio         = 70
       MaxHeapSize              = 107374182400 (102400.0MB)
       NewSize                  = 1363144 (1.2999954223632812MB)
       MaxNewSize               = 17592186044415 MB
       OldSize                  = 5452592 (5.1999969482421875MB)
       NewRatio                 = 2
       SurvivorRatio            = 8
       MetaspaceSize            = 21807104 (20.796875MB)
       CompressedClassSpaceSize = 1073741824 (1024.0MB)
       MaxMetaspaceSize         = 1073741824 (1024.0MB)
       G1HeapRegionSize         = 0 (0.0MB)
    
    Heap Usage:
     ZHeap          used 82988M, capacity 1024M, max capacity 27112449862M
    

    对于最大容量还有其他虚拟机选项吗? ZGC 堆如何工作?

    最佳答案

    由于这个问题时常被问到,而且我已经厌倦了解释它,所以让我尝试将其放在这里,以便人们可以简单地搜索,得到他们的答案,并再次快乐(即使是很短的一段时间)时间长了,还是值得的!)。

    ZGC 的 RSS 过度报告是由于 ZGC 使用的内存页面操作技术(即多重映射)造成的。由于 ZGC 本质上是 Zing C4 收集器(由 Azul Systems 开发)的另一种实现,因此 Zing 也存在相同的“过度报告”RSS 问题。

    查看这段代码:

    http://hg.openjdk.java.net/zgc/zgc/file/59c07aef65ac/src/hotspot/os_cpu/linux_x86/zPhysicalMemoryBacking_linux_x86.cpp#l160

    void ZPhysicalMemoryBacking::map(ZPhysicalMemory pmem, uintptr_t offset) const {
      if (ZUnmapBadViews) {
        // Only map the good view, for debugging only
        map_view(pmem, ZAddress::good(offset), AlwaysPreTouch);
      } else {
        // Map all views
        map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch);
        map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch);
        map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch);
      }
    }
    

    还有这个:

    void ZPhysicalMemoryBacking::map_view(ZPhysicalMemory pmem, uintptr_t addr, bool pretouch) const {
      const size_t nsegments = pmem.nsegments();
      // Map segments
      for (size_t i = 0; i < nsegments; i++) {
        const ZPhysicalMemorySegment segment = pmem.segment(i);
        const size_t size = segment.size();
        const void* const res = mmap((void*)addr, size, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_SHARED, _file.fd(), segment.start());
        if (res == MAP_FAILED) {
          ZErrno err;
          map_failed(err);
        }
        // Advise on use of transparent huge pages before touching it
        if (ZLargePages::is_transparent()) {
          advise_view(addr, size);
        }
        // NUMA interleave memory before touching it
        ZNUMA::memory_interleave(addr, size);
        if (pretouch) {
          pretouch_view(addr, size);
        }
        addr += size;
      }
    }
    

    映射所有 View :

    • map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch);
    • map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch);
    • map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch);

    这意味着对于同一个地址,ZGC 会将其映射到 3 个不同的 View :marked0、marked1 和 remapped。这三个 View 反射(reflect)在虚拟内存地址中。这意味着,3个不同的虚拟内存地址将被映射到同一个底层物理内存,因此对于每个物理内存页,都有3个虚拟页映射到它。

    如果 ZGC 成长为分代 GC(其中有年轻代和老年代,而不是像 ZGC 现在那样只有单代),我们预计这个数字也会增加到 xmx 堆大小的 6 倍.

    这就是为什么 Azul Zing 和 Oracle ZGC 使用的多重映射使人们在“top”命令下陷入 panic 模式。但请注意,报告的只是虚拟内存空间,因此除非您的系统工具遇到这个令人困惑的部分,否则您没有理由调用 911。

    关于java - ZGC最大堆大小超过物理内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57899020/

    相关文章:

    java - 如何处理具有不同参数的相同 URL?

    java - Guava 事件总线 : How to return result from event handler

    java - 如何创建具有平均深度的文件夹和子文件夹

    java - 使用 arraylist 删除数组中的重复项失败

    Java - 服务器参数

    Elasticsearch 忽略我的 JVM 堆大小设置

    java - JVM Runtime.getRuntime().availableProcessors() 在 AWS ECS Fargate 上返回 1

    java - 滚动后 GridView 项的选定背景消失

    java - 卡尺错误 : CICompilerCount of 1 is invalid; must be at least 2

    java - 通过 Spring Batch 部分读取和写入数据 - OutOfMemoryError : GC overhead limit exceeded