JDK 1.8 -XX:+UseLargePages 在 os 上剩余的大页面不足时的行为

JDK 1.8 -XX:+UseLargePages behavior when there's not enough huge pages left on os

我目前对如何优化使用 HugePages 和 JVM 应用程序与 Netty,启用 -XX:+UseLargePages 选项,并使用 G1Gc[=26= 感到困惑].
另外,我没有忘记设置相同的堆和元空间的最大和最小大小。

我的应用程序看起来不错,但我想知道 如果系统上没有剩余的可用大页面 会发生什么,因为 JVM 使用额外的本机内存区域来分配直接内存缓冲区等。
(假设应用程序正常启动,并在堆外内存区域消耗额外的HugePages。)

我已阅读下一页,但没有描述 JVM 无法分配大页面时的行为。 https://www.oracle.com/java/technologies/javase/largememory-pages.html

我使用 CentOS 7 和 OpenJDK 1.8。0_151-b12 作为部署前的测试平台。

如果分配大页面失败,OpenJDK 8 或更高版本回退到分配常规页面。

src/hotspot/share/memory/virtualspace.cpp:

    if (base != NULL) {
[...]
    } else {
      // failed; try to reserve regular memory below
      if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
                            !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
        log_debug(gc, heap, coops)("Reserve regular memory without large pages");
      }
    }

所有 GC 实现都使用 ReservedSpace 助手来分配内存,因此这不是特定于 GC 的。

您可以通过限制可用的大页面轻松地在 Linux 上测试该行为:

$ echo 16 > /proc/sys/vm/nr_hugepages
$ cat /proc/meminfo  | grep HugePages
AnonHugePages:     40960 kB
HugePages_Total:      16
HugePages_Free:       16
HugePages_Rsvd:        0
HugePages_Surp:        0
$ java -XX:+UseLargePages Test
OpenJDK 64-Bit Server VM warning: Failed to reserve large pages memory req_addr: 0x0000000000000000 bytes: 251658240 (errno = 12).
OpenJDK 64-Bit Server VM warning: Failed to reserve large pages memory req_addr: 0x0000000707c00000 bytes: 4164943872 (errno = 12).
OpenJDK 64-Bit Server VM warning: Failed to reserve large pages memory req_addr: 0x0000000000000000 bytes: 67108864 (errno = 12).
OpenJDK 64-Bit Server VM warning: Failed to reserve large pages memory req_addr: 0x0000000000000000 bytes: 67108864 (errno = 12).
$ echo $?
0

strace 确认失败的分配尝试和成功的重试,大小相同但没有 MAP_HUGETLB:

11631 mmap(NULL, 251658240, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0) = -1 ENOMEM (Cannot allocate memory)
11631 mmap(NULL, 251658240, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7f35d489c000