2017-04-04 26 views
5

Javaヒープ割り当てが2MBの倍数であることに気付きました。たとえば、-Xmx values as 1021m, 1022mというJVMを開始し、両方のJVMがヒープサイズ1022mで開始されました。同様にヒープサイズ1023m,1024m1024mで始まります。Javaヒープ割り当てが2MBの倍数である

出力は、以下である:両方の場合において

C:\Users\myuser>java -Xmx1021m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize" 
    uintx MaxHeapSize        := 1071644672 
      {product} 
java version "1.8.0_121" 
Java(TM) SE Runtime Environment (build 1.8.0_121-b13) 
Java HotSpot(TM) Client VM (build 25.121-b13, mixed mode) 

C:\Users\myuser>java -Xmx1022m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize" 
    uintx MaxHeapSize        := 1071644672 
      {product} 
java version "1.8.0_121" 
Java(TM) SE Runtime Environment (build 1.8.0_121-b13) 
Java HotSpot(TM) Client VM (build 25.121-b13, mixed mode) 

それは1022メガバイトである1071644672のバイトとしてMaxHeapSizeを示しています。両方の場合において

C:\Users\myuser>java -Xmx1023m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize" 
    uintx MaxHeapSize        := 1073741824 
      {product} 
java version "1.8.0_121" 
Java(TM) SE Runtime Environment (build 1.8.0_121-b13) 
Java HotSpot(TM) Client VM (build 25.121-b13, mixed mode) 

C:\Users\myuser>java -Xmx1024m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize" 
    uintx MaxHeapSize        := 1073741824 
      {product} 
java version "1.8.0_121" 
Java(TM) SE Runtime Environment (build 1.8.0_121-b13) 
Java HotSpot(TM) Client VM (build 25.121-b13, mixed mode) 

それは1024メガバイトである1073741824のバイトとしてMaxHeapSizeを示しています。

この動作はXmsに似ています。

質問1:ヒープサイズが指定された値から2の倍数に変更されるのはなぜですか?

質問2:フラグかのヒープを作成するために、JVMを強制的にいくつかの方法があります:JVMが実際に

質問3を指定したものとは異なる値で開始されたとき、なぜJavaがさえ私たちに警告しません。 1021mb?

質問4:仮想マシンで1023MBの空きメモリがあり、1023MBのヒープを持つJVMを作成しようとしています。上記の動作によって、実際には利用できない1024MBで開始しようとします。 JVMの作成に失敗しますか?

+1

これはJVMではなくオペレーティングシステムの制限だと思います。オペレーティングシステムには通常、「メモリページ」という概念があります。これは処理に割り当てられる物理メモリの量が最小限です。各プロセスは多数のページを持つことができますが、1ページ以上はありません。お使いのOSのページサイズは2MBです。 –

+0

@ M.Prokhorovあなたのコメントはほぼ正しいです、唯一の修正は最小量の*仮想*メモリです。メモリページをより単純にする - 仮想、メモリフレーム - 物理。 – Eugene

+0

@Eugene WindowsとLinuxのプロセスで、最小限の仮想メモリを取得する方法を教えてください。 –

答えて

2

これは実際にはかなり面白いです。したがって、と同時にでサポートされているページサイズは2つあり、hereと記載されています。

4KBです。他の2つはhuge pagesと呼ばれます。

これを見ると、1つのページサイズが2MBであることがわかります。問題が解決したと言うことができます。

あなたが知っているので、あなたのメモリは実際にあなたの例とちょうど2MBの塊で整列しています。あなたの質問を読むと、それは実際に私の最初の反応でした。しかし、私は私のMACを試してみることにしました。今私が持っているCPUは、明らかにすべての3ページサイズをサポートするx86です:4KB、2MB、1GB。

Mac OS自体はどうですか?実際にページサイズの値が読み取られているソースの値(jdk-9)は、hotspot/src/os/bsd/vm/os_bsd.cppです。そして、実際のコード:

Bsd::set_page_size(getpagesize()) 

は、私はそのシンプルな機能getpagesizeを取り、Xcodeでそれを実行します。サプライズ、驚き! 4KBのみですが、ヒープはあなたの例のようにまだ整列しています(MB)。

次に、ここでpage_sizeに整列が行われていることを思い出しました。share/vm/memory/heap.cpp。ここでは、実際のメソッドです:

static size_t align_to_page_size(size_t size) { 
    const size_t alignment = (size_t)os::vm_page_size(); 
    assert(is_power_of_2(alignment), "no kidding ???"); 
    return (size + alignment - 1) & ~(alignment - 1); 
} 

それはPAGE_SIZE(私の場合は4KB)で割り切れるように、メモリが少しだけ成長させるでしょう。それはちょうど4KBで割り切れることについてのコメントであなたが言ったものです。

次に、私はかなりの検索を行いました... jdk-9-sources|grep Xmxと私は幸運を得ました!私が見つけた幸運のビットはここにある:私はこれが2MB上に整列し、ヒープを作る唯一のものであることを非常にを確認していないこの時点で

size_t CollectorPolicy::compute_heap_alignment() { 
    // The card marking array and the offset arrays for old generations are 
    // committed in os pages as well. Make sure they are entirely full (to 
    // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1 
    // byte entry and the os page size is 4096, the maximum heap size should 
    // be 512*4096 = 2MB aligned. 

    size_t alignment = CardTableRS::ct_max_alignment_constraint(); 

    if (UseLargePages) { 
     // In presence of large pages we have to make sure that our 
     // alignment is large page aware. 
     alignment = lcm(os::large_page_size(), alignment); 
    } 

    return alignment; 
} 

share/vm/gc/shared/collectorPolicy.cppと素晴らしいコメント。この不確かさは、このファイルがフルであるという事実から来ています。はいくつかのパラメータを調整するためにヒープを成長させる方法に関するコメントです。それらの細部すべてを理解することは楽しいでしょうが、は極端に時間がかかります、私はあきらめました。

+0

うわー、優れた発見。 –

0

ご使用のオペレーティングシステムによって課される制限であり、JVMでは制限があります。 プロセスにメモリを割り当てるとき、オペレーティングシステムは通常、バイトを操作しません(そうすることで、割り当てが行われ、特にメモリへのアクセスが非常に遅くなるため、「メモリページ」と呼ばれます)。 hereから始まる詳細を読むことができます。

オペレーティングシステムのメモリページサイズは2MBと思われます。つまり、プロセス要求によってメモリが割り当てられると、最小限のメモリしか使用できません。これは2MBです。

質問の2番目の部分では、オペレーティングシステムのメモリページサイズを変更することで、2Mバイトの倍数でないヒープをJVMに強制することができます(その中にはこのオプションがあります)。しかし、それはそのOSの中で実行されているすべてのプロセスに影響するため、予期しない結果を招く可能性があります。

+0

残念ながら、それはそうではありません。私はページサイズが4KBの私のMacでそれを走らせた。 BSDでpage_sizeがどのように計算されるかについてのjdk-9の情報源を調べました: 'hotspot/src/os/bsd/vm/os_bsd.cpp'にある' Bsd :: set_page_size(getpagesize()); 'getpagesize()'を実行すると4KBが返されますので、これ以上のことがあります... – Eugene

+0

@Eugene、ホットスポットソースを見ているなら、 'Universe.cpp'に' preferred_heap_base() 'があります。私は多くの変数が移動されているので(と私はそのコードの専門家からは遠いですが)サイズを整列するように見えるので、正確に何をしているのか分かりません。と。 –

+0

私はここで問題を発見したと思うし、答えを提出する。 – Eugene

関連する問題