Java:ヒープサイズはどのように決定されるのか?

一般に、Javaプログラムがメモリ不足に陥った場合には、VMに-Xmxフラグをつけて最大ヒープサイズを指定しろと言われるのだが、そもそもデフォルトの最大ヒープサイズはどのように決定されるのだろうか?以下に答えがあった。

これによると、一般的にはマシンの物理メモリの1/4か、あるいは1GBの小さい方だという。ということは、いくら物理メモリを積んでいても、1GBにしかならないということ(と解釈したが、テストしてみた限りでは1/4が採用されている)。

デフォルトの値を見るには、以下を実行する(Windowsの場合)

java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSize ThreadStackSize"

手元のAdoptOpenJDK12でやってみると以下になった。物理メモリは8GB。

C:\Users\admin>java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSiz
e ThreadStackSize"
     intx CompilerThreadStackSize                  = 0
            {pd product} {default}
   size_t ErgoHeapSizeLimit                        = 0
               {product} {default}
   size_t HeapSizePerGCThread                      = 43620760
               {product} {default}
   size_t InitialHeapSize                          = 132120576
               {product} {ergonomic}
   size_t LargePageHeapSizeThreshold               = 134217728
               {product} {default}
   size_t MaxHeapSize                              = 2111832064
               {product} {ergonomic}
    uintx NonNMethodCodeHeapSize                   = 5830732
            {pd product} {ergonomic}
    uintx NonProfiledCodeHeapSize                  = 122913754
            {pd product} {ergonomic}
    uintx ProfiledCodeHeapSize                     = 122913754
            {pd product} {ergonomic}
     intx ThreadStackSize                          = 0
            {pd product} {default}
     intx VMThreadStackSize                        = 0
            {pd product} {default}
openjdk version "12.0.1" 2019-04-16
OpenJDK Runtime Environment AdoptOpenJDK (build 12.0.1+12)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 12.0.1+12, mixed mode, sharing)

ということで、MaxHeapSizeは2GBになっている。次に、-Xmxフラグをつけてみる。物理メモリをはるかに超える-Xmx16gを指定する。

C:\Users\admin>java -Xmx16g -XX:+PrintFlagsFinal -version | findstr /i "HeapSize
 PermSize ThreadStackSize"
     intx CompilerThreadStackSize                  = 0
            {pd product} {default}
   size_t ErgoHeapSizeLimit                        = 0
               {product} {default}
   size_t HeapSizePerGCThread                      = 43620760
               {product} {default}
   size_t InitialHeapSize                          = 134217728
               {product} {ergonomic}
   size_t LargePageHeapSizeThreshold               = 134217728
               {product} {default}
   size_t MaxHeapSize                              = 17179869184
               {product} {command line}
    uintx NonNMethodCodeHeapSize                   = 5830732
            {pd product} {ergonomic}
    uintx NonProfiledCodeHeapSize                  = 122913754
            {pd product} {ergonomic}
    uintx ProfiledCodeHeapSize                     = 122913754
            {pd product} {ergonomic}
     intx ThreadStackSize                          = 0
            {pd product} {default}
     intx VMThreadStackSize                        = 0
            {pd product} {default}
openjdk version "12.0.1" 2019-04-16
OpenJDK Runtime Environment AdoptOpenJDK (build 12.0.1+12)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 12.0.1+12, mixed mode, sharing)

たしかに、16G(実際には17GB)と表示されている。