Java Platform, Standard Editionトラブルシューティング・ガイド
目次      

2.7 ネイティブ・メモリー・トラッキング

ネイティブ・メモリー・トラッキング(NMT)は、Java HotSpot VMの内部メモリー使用状況を追跡するJava HotSpot VM機能です。 NMTのスコープ、NMTを有効にする方法、およびその他の使用の詳細は、ネイティブ・メモリー・トラッキングを参照してください。

NMTでは、非JVMコードによるメモリーの割当てを追跡しないので、ネイティブ・コードのメモリー・リークを検出するには、オペレーティング・システムでサポートされたツールの使用が必要になる場合があります。

次の項では、VM内部メモリー割当てのモニターおよびVMメモリー・リークの診断方法について説明します。

2.7.1 NMTによるメモリー・リークの検出

メモリー・リークを検出するには、これらのステップを実行します。

  1. 次のコマンドライン・オプションを使用して、サマリーまたは詳細なトラッキングが指定されたJVMを起動します: -XX:NativeMemoryTracking=summaryまたは-XX:NativeMemoryTracking=detail

  2. 初期のベースラインの確立 - NMTベースライン機能を使用して、開発とメンテナンスのときに比較するベースラインを取得するには、次を実行します: jcmd <pid> VM.native_memory baseline

  3. 次を使用して、メモリーの変更をモニターします: jcmd <pid> VM.native_memory detail.diff

  4. アプリケーションのメモリー・リークが少量の場合、それが明らかになるまで時間がかかる場合があります。

2.7.2 VM内部メモリーをモニターする方法

ネイティブ・メモリー・トラッキングをjcmdユーティリティとともに使用して、メモリーをモニターし、開発またはメンテナンス時にアプリケーションのメモリー使用量の増加が開始されないように設定できます。 NMTのメモリー・カテゴリの詳細は、表2-1を参照してください。

次の項では、NMTのサマリーまたは詳細データを取得する方法、およびサンプル出力の解釈の方法を説明します。

  • サンプル出力の解釈: 以下のサンプル出力から、予約済メモリーとコミット済メモリーを確認できます。 コミット済メモリーのみが実際に使用されることに注意してください。 たとえば、-Xms100m -Xmx1000mで実行した場合、JVMでは1000MBがJavaヒープ用に予約されます。 初期のヒープ・サイズは100MBのみであるため、最初に100MBのみがコミットされます。 アドレス領域がほぼ無制限である64ビット・マシンの場合、JVMで多くのメモリーが予約されても問題はありません。 コミットされるメモリーが次第に増加し、スワッピングやネイティブOOM状態になる可能性がある場合に、問題が発生します。

    Arenaは、mallocを使用して割り当てられるメモリー・チャンクです。 スコープを終了またはコード領域を離れるとき、これらのチャンクからメモリーがバルクで解放されます。 これらのチャンクは、一時メモリーを保持するために他のサブシステムで再利用できます(プリスレッドの割当てなど)。 Arenaのmallocポリシーは、メモリー・リークがないことを確認します。 したがって、個々のオブジェクトではなく、Arena全体が追跡されます。 初期のメモリー量の一部は追跡できません。

    NMTを有効にすると、JVMパフォーマンスが5-10%低下し、NMTのメモリー使用量により、すべてのmallocメモリーに2つのマシン・ワードがmallocヘッダーとして追加されます。 NMTのメモリー使用量も、NMTにより追跡されます。

  • サマリー・データの取得: ネイティブ・メモリー使用量のサマリー・ビューを取得するには、次のコマンドライン・オプションを使用してJVMを起動します: -XX:NativeMemoryTracking=summary

    例2-2は、追跡レベルがサマリーに設定されたNMTを示すサンプル出力です。 このサンプル出力を得るための1つの方法は、jcmd <pid> VM.native_memory summaryを実行することです。

    例2-2 NMTのサマリー・データの取得

    Total:  reserved=664192KB,  committed=253120KB                                           <--- total memory tracked by Native Memory Tracking
     
    -                 Java Heap (reserved=516096KB, committed=204800KB)                      <--- Java Heap
                                (mmap: reserved=516096KB, committed=204800KB)
     
    -                     Class (reserved=6568KB, committed=4140KB)                          <--- class metadata
                                (classes #665)                                               <--- number of loaded classes
                                (malloc=424KB, #1000)                                        <--- malloc'd memory, #number of malloc
                                (mmap: reserved=6144KB, committed=3716KB)
     
    -                    Thread (reserved=6868KB, committed=6868KB)
                                (thread #15)                                                 <--- number of threads
                                (stack: reserved=6780KB, committed=6780KB)                   <--- memory used by thread stacks
                                (malloc=27KB, #66)
                                (arena=61KB, #30)                                            <--- resource and handle areas
     
    -                      Code (reserved=102414KB, committed=6314KB)
                                (malloc=2574KB, #74316)
                                (mmap: reserved=99840KB, committed=3740KB)
     
    -                        GC (reserved=26154KB, committed=24938KB)
                                (malloc=486KB, #110)
                                (mmap: reserved=25668KB, committed=24452KB)
     
    -                  Compiler (reserved=106KB, committed=106KB)
                                (malloc=7KB, #90)
                                (arena=99KB, #3)
     
    -                  Internal (reserved=586KB, committed=554KB)
                                (malloc=554KB, #1677)
                                (mmap: reserved=32KB, committed=0KB)
     
    -                    Symbol (reserved=906KB, committed=906KB)
                                (malloc=514KB, #2736)
                                (arena=392KB, #1)
     
    -           Memory Tracking (reserved=3184KB, committed=3184KB)
                                (malloc=3184KB, #300)
     
    -        Pooled Free Chunks (reserved=1276KB, committed=1276KB)
                                (malloc=1276KB)
     
    -                   Unknown (reserved=33KB, committed=33KB)
                                (arena=33KB, #1)
    
  • 詳細データの取得: ネイティブ・メモリー使用量の詳細ビューを取得するには、次のコマンドライン・オプションを使用してJVMを起動します: -XX:NativeMemoryTracking=detail これは、最も多くのメモリーを割り当てるメソッドを正確に追跡します。 NMTを有効にすると、JVMパフォーマンスが5-10%低下し、NMTのメモリー使用量により、すべてのmallocメモリーに2ワードがmallocヘッダーとして追加されます。 NMTのメモリー使用量も、NMTにより追跡されます。

    例2-3は、追跡レベルが詳細に設定された仮想メモリーのサンプル出力を示しています。 このサンプル出力を得るための1つの方法は、jcmd <pid> VM.native_memory detailを実行することです。

    例2-3 NMTの詳細データの取得

    Virtual memory map:
     
    [0x8f1c1000 - 0x8f467000] reserved 2712KB for Thread Stack
                    from [Thread::record_stack_base_and_size()+0xca]
            [0x8f1c1000 - 0x8f467000] committed 2712KB from [Thread::record_stack_base_and_size()+0xca]
     
    [0x8f585000 - 0x8f729000] reserved 1680KB for Thread Stack
                    from [Thread::record_stack_base_and_size()+0xca]
            [0x8f585000 - 0x8f729000] committed 1680KB from [Thread::record_stack_base_and_size()+0xca]
     
    [0x8f930000 - 0x90100000] reserved 8000KB for GC
                    from [ReservedSpace::initialize(unsigned int, unsigned int, bool, char*, unsigned int, bool)+0x555]
            [0x8f930000 - 0x90100000] committed 8000KB from [PSVirtualSpace::expand_by(unsigned int)+0x95]
     
    [0x902dd000 - 0x9127d000] reserved 16000KB for GC
                    from [ReservedSpace::initialize(unsigned int, unsigned int, bool, char*, unsigned int, bool)+0x555]
            [0x902dd000 - 0x9127d000] committed 16000KB from [os::pd_commit_memory(char*, unsigned int, unsigned int, bool)+0x36]
     
    [0x9127d000 - 0x91400000] reserved 1548KB for Thread Stack
                    from [Thread::record_stack_base_and_size()+0xca]
            [0x9127d000 - 0x91400000] committed 1548KB from [Thread::record_stack_base_and_size()+0xca]
     
    [0x91400000 - 0xb0c00000] reserved 516096KB for Java Heap                                                                            <--- reserved memory range
                    from [ReservedSpace::initialize(unsigned int, unsigned int, bool, char*, unsigned int, bool)+0x190]                  <--- callsite that reserves the memory
            [0x91400000 - 0x93400000] committed 32768KB from [VirtualSpace::initialize(ReservedSpace, unsigned int)+0x3e8]               <--- committed memory range and its callsite
            [0xa6400000 - 0xb0c00000] committed 172032KB from [PSVirtualSpace::expand_by(unsigned int)+0x95]                             <--- committed memory range and its callsite
     
    [0xb0c61000 - 0xb0ce2000] reserved 516KB for Thread Stack
                    from [Thread::record_stack_base_and_size()+0xca]
            [0xb0c61000 - 0xb0ce2000] committed 516KB from [Thread::record_stack_base_and_size()+0xca]
     
    [0xb0ce2000 - 0xb0e83000] reserved 1668KB for GC
                    from [ReservedSpace::initialize(unsigned int, unsigned int, bool, char*, unsigned int, bool)+0x555]
            [0xb0ce2000 - 0xb0cf0000] committed 56KB from [PSVirtualSpace::expand_by(unsigned int)+0x95]
            [0xb0d88000 - 0xb0d96000] committed 56KB from [CardTableModRefBS::resize_covered_region(MemRegion)+0xebf]
            [0xb0e2e000 - 0xb0e83000] committed 340KB from [CardTableModRefBS::resize_covered_region(MemRegion)+0xebf]
     
    [0xb0e83000 - 0xb7003000] reserved 99840KB for Code
                    from [ReservedSpace::initialize(unsigned int, unsigned int, bool, char*, unsigned int, bool)+0x555]
            [0xb0e83000 - 0xb0e92000] committed 60KB from [VirtualSpace::initialize(ReservedSpace, unsigned int)+0x3e8]
            [0xb1003000 - 0xb139b000] committed 3680KB from [VirtualSpace::initialize(ReservedSpace, unsigned int)+0x37a]
     
    [0xb7003000 - 0xb7603000] reserved 6144KB for Class
                    from [ReservedSpace::initialize(unsigned int, unsigned int, bool, char*, unsigned int, bool)+0x555]
            [0xb7003000 - 0xb73a4000] committed 3716KB from [VirtualSpace::initialize(ReservedSpace, unsigned int)+0x37a]
     
    [0xb7603000 - 0xb760b000] reserved 32KB for Internal
                    from [PerfMemory::create_memory_region(unsigned int)+0x8ba]
     
    [0xb770b000 - 0xb775c000] reserved 324KB for Thread Stack
                    from [Thread::record_stack_base_and_size()+0xca]
            [0xb770b000 - 0xb775c000] committed 324KB from [Thread::record_stack_base_and_size()+0xca]
    
  • NMTベースラインからの差分の取得: サマリーおよび詳細レベルの追跡では、アプリケーションが起動され実行されているとき、ベースラインを設定できます。 これを行うには、アプリケーションのウォーム・アップ後にjcmd <pid> VM.native_memory baselineを実行します。 次に、jcmd <pid> VM.native_memory summary.diffまたはjcmd <pid> VM.native_memory detail.diffを実行できます。

    例2-4は、ベースライン以降に使用されたネイティブ・メモリーの差分サマリーのサンプル出力を示し、これはメモリー・リークを見つけるのに優れた方法です。

    例2-4 NMTベースラインからの差分の取得

    Total:  reserved=664624KB  -20610KB, committed=254344KB -20610KB                         <--- total memory changes vs. earlier baseline. '+'=increase '-'=decrease
     
    -                 Java Heap (reserved=516096KB, committed=204800KB)
                                (mmap: reserved=516096KB, committed=204800KB)
     
    -                     Class (reserved=6578KB +3KB, committed=4530KB +3KB)
                                (classes #668 +3)                                            <--- 3 more classes loaded
                                (malloc=434KB +3KB, #930 -7)                                 <--- malloc'd memory increased by 3KB, but number of malloc count decreased by 7
                                (mmap: reserved=6144KB, committed=4096KB)
     
    -                    Thread (reserved=60KB -1129KB, committed=60KB -1129KB)
                                (thread #16 +1)                                              <--- one more thread
                                (stack: reserved=7104KB +324KB, committed=7104KB +324KB)
                                (malloc=29KB +2KB, #70 +4)
                                (arena=31KB -1131KB, #32 +2)                                 <--- 2 more arenas (one more resource area and one more handle area)
     
    -                      Code (reserved=102328KB +133KB, committed=6640KB +133KB)
                                (malloc=2488KB +133KB, #72694 +4287)
                                (mmap: reserved=99840KB, committed=4152KB)
     
    -                        GC (reserved=26154KB, committed=24938KB)
                                (malloc=486KB, #110)
                                (mmap: reserved=25668KB, committed=24452KB)
     
    -                  Compiler (reserved=106KB, committed=106KB)
                                (malloc=7KB, #93)
                                (arena=99KB, #3)
     
    -                  Internal (reserved=590KB +35KB, committed=558KB +35KB)
                                (malloc=558KB +35KB, #1699 +20)
                                (mmap: reserved=32KB, committed=0KB)
     
    -                    Symbol (reserved=911KB +5KB, committed=911KB +5KB)
                                (malloc=519KB +5KB, #2921 +180)
                                (arena=392KB, #1)
     
    -           Memory Tracking (reserved=2073KB -887KB, committed=2073KB -887KB)
                                (malloc=2073KB -887KB, #84 -210)
     
    -        Pooled Free Chunks (reserved=2624KB -15876KB, committed=2624KB -15876KB)
                                (malloc=2624KB -15876KB)
    

    例2-5は、ベースライン以降に使用されたネイティブ・メモリーの差分詳細を示すサンプル出力で、これはメモリー・リークを見つけるのに優れた方法です。

    例2-5 NMTの差分詳細の取得

    Details:
     
    [0x01195652] ChunkPool::allocate(unsigned int)+0xe2
                                (malloc=482KB -481KB, #8 -8)
     
    [0x01195652] ChunkPool::allocate(unsigned int)+0xe2
                                (malloc=2786KB -19742KB, #134 -618)
     
    [0x013bd432] CodeBlob::set_oop_maps(OopMapSet*)+0xa2
                                (malloc=591KB +6KB, #681 +37)
     
    [0x013c12b1] CodeBuffer::block_comment(int, char const*)+0x21                <--- [callsite address] method name + offset
                                (malloc=562KB +33KB, #35940 +2125)               <--- malloc'd amount, increased by 33KB #malloc count, increased by 2125
     
    [0x0145f172] ConstantPool::ConstantPool(Array<unsigned char>*)+0x62
                                (malloc=69KB +2KB, #610 +15)
     
    ...
     
    [0x01aa3ee2] Thread::allocate(unsigned int, bool, unsigned short)+0x122
                                (malloc=21KB +2KB, #13 +1)
     
    [0x01aa73ca] Thread::record_stack_base_and_size()+0xca
                                (mmap: reserved=7104KB +324KB, committed=7104KB +324KB)
    
目次      

Copyright © 1993, 2025, Oracle and/or its affiliates. All rights reserved.