2016-08-07 15 views
-1

Java GCでこの奇妙な動作が発生しました。Javaガベージコレクタの奇妙な動作

アプリケーションの最大ヒープが1GBで、GCオーバーヘッドの上限を超えたエラーが発生しました。

これはjmap -heapの出力です。

Heap Configuration: 
    MinHeapFreeRatio   = 40 
    MaxHeapFreeRatio   = 70 
    MaxHeapSize    = 1610612736 (1536.0MB) 
    NewSize     = 1572864 (1.5MB) 
    MaxNewSize    = 536870912 (512.0MB) 
    OldSize     = 1072168960 (1022.5MB) 
    NewRatio     = 2 
    SurvivorRatio   = 8 
    MetaspaceSize   = 21807104 (20.796875MB) 
    CompressedClassSpaceSize = 1073741824 (1024.0MB) 
    MaxMetaspaceSize   = 17592186044415 MB 
    G1HeapRegionSize   = 0 (0.0MB) 
Heap Usage: 
PS Young Generation 
Eden Space: 
    capacity = 37224448 (35.5MB) 
    used  = 34328776 (32.73847198486328MB) 
    free  = 2895672 (2.7615280151367188MB) 
    92.2210478446853% used 
From Space: 
    capacity = 1572864 (1.5MB) 
    used  = 786432 (0.75MB) 
    free  = 786432 (0.75MB) 
    50.0% used 
To Space: 
    capacity = 1572864 (1.5MB) 
    used  = 0 (0.0MB) 
    free  = 1572864 (1.5MB) 
    0.0% used 
PS Old Generation 
    capacity = 1072168960 (1022.5MB) 
    used  = 13918336 (13.2735595703125MB) 
    free  = 1058250624 (1009.2264404296875MB) 
    1.2981476352383863% used 

だから我々は次のパラメータでGCをチューニング。

-XX:NewSize=512 
-XX:MaxNewSize=512 
-XX:SurvivorRatio=16 
-XX:NewRatio=1 

NewSizeパラメータとMaxNewSizeをMB単位で設定されることになりました。

しかし、この構成では、次のヒープマップが得られます。

Heap Configuration: 
    MinHeapFreeRatio   = 40 
    MaxHeapFreeRatio   = 70 
    MaxHeapSize    = 2147483648 (2048.0MB) 
    NewSize     = 1572864 (1.5MB) 
    MaxNewSize    = 1572864 (1.5MB) 
    OldSize     = 1072168960 (1022.5MB) 
    NewRatio     = 1 
    SurvivorRatio   = 16 
    MetaspaceSize   = 21807104 (20.796875MB) 
    CompressedClassSpaceSize = 1073741824 (1024.0MB) 
    MaxMetaspaceSize   = 17592186044415 MB 
    G1HeapRegionSize   = 0 (0.0MB) 
Heap Usage: 
PS Young Generation 
Eden Space: 
    capacity = 524288 (0.5MB) 
    used  = 200200 (0.19092559814453125MB) 
    free  = 324088 (0.30907440185546875MB) 
    38.18511962890625% used 
From Space: 
    capacity = 524288 (0.5MB) 
    used  = 98304 (0.09375MB) 
    free  = 425984 (0.40625MB) 
    18.75% used 
To Space: 
    capacity = 524288 (0.5MB) 
    used  = 0 (0.0MB) 
    free  = 524288 (0.5MB) 
    0.0% used 
PS Old Generation 
    capacity = 1072168960 (1022.5MB) 
    used  = 522704656 (498.49000549316406MB) 
    free  = 549464304 (524.0099945068359MB) 
    48.752078776837564% used 

今エデンスペースの容量はわずか0.5メガバイトですが、それだけで以前に92%であったと容量は35メガバイトだったの38%を使用しています。 旧世代の利用率は50%まで上昇しましたが、これは以前は約2%でした。

誰でもGCがこのように動作する理由を説明できますか?

+0

* "NewSizeとMaxNewSizeはMBで設定されているはずです" * - なぜMBで設定していないのですか? – the8472

+0

私たちは既にそれを設定しました。しかし、この前述の行動の理由を知りたい。 –

+0

使用可能なシステムメモリの総量はどれくらいですか?-Xmsと-Xmxに設定する値 – ravthiru

答えて

0

私はついにその理由を見つけることができました。

JVMがオブジェクトのヒープ割り当てを試みるとき、まず、対応するTLAB(スレッドローカル割り当てバッファ)の使用可能なサイズをチェックし、十分でない場合は、それを拡張しようとします。 残りのエデンスペースのサイズがTLAB拡張に十分でない場合、JVMはエデンスペース自体を探します。 Eden空間の残りのサイズも十分ではない場合、JVMはオブジェクトをOld Gen空間に直接割り当てます。

それ以外の場合、NewGenのサイズが小さいと、Eden空間だけでなく、両方の生存空間も小さくなります(通常8または16回)。したがって、たとえJVMがEdenのスペースにスペースを割り当てることができたとしても、これらのオブジェクトが少数の少数のコレクションのために生き残ることができれば。サバイバースペースはオーバーフローし、OldGenスペースに移動します。