14

を使用して特定のファイルをメモリマッピングすることにより、2 つ以上の JVM 間で一種の共有キャッシュを実装しようとしていましたMappedByteBufferMappedByteBuffer.load()仕様から、使用時にデータを直接バッファにロードする必要があることがわかります。これについていくつか質問があります。

私のコードスニペット::

RandomAccessFile file = new RandomAccessFile("file.txt","rw");
FileChannel fc = file.getChannel();
MappedByteBuffer buf5 = fc.map(MapMode.READ_WRITE, 0, fc.size());

//ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);

buf5.load();

try
{
    Class c = Class.forName("java.nio.Bits");
    Field f = c.getDeclaredField("reservedMemory");
    f.setAccessible(true);
    long reservedMemory = f.getLong(null);
    f = c.getDeclaredField("maxMemory");
    f.setAccessible(true);
    System.out.println(
            "Direct Memory Usage: "+ reservedMemory +"/"+ f.getLong(null)+"\n");
}
catch (Throwable t)
{
}
  1. 上記のコードの出力は、直接メモリ使用量が 0 バイトです (File.txt は 1 GB)。しかし、行のコメントを外すと..

    ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);
    

    Direct Memory Usage は 100MB です。そもそもなぜ直接メモリを使用していないのか(つまり、行がコメントアウトされているとき)、なぜそうなのか理解できません

  2. 上記のコードの直接メモリ使用量は 0 B ですが、プロセスの常駐メモリ ( unix top を使用) が 1 GB 増加していることがわかります。しかし、ボックスで「free -m」を実行しても、メモリ使用量の増加は見られません。

どちらの場合も、メモリがどこに行き着くのかについて少し混乱しています。

ありがとう!

4

1 に答える 1

26

Direct ByteBuffers(ByteBuffer.allocateDirectを使用して割り当てられたもの)は、メモリのさまざまなセクションを表し、割り当てが異なるという点でMappedByteBuffersとは異なります。Direct ByteBuffersは、一般にmalloc呼び出しで割り当てられたJVMの外部に割り当てられたメモリのブロックにアクセスする方法です(ただし、ほとんどの実装では、おそらく効率的なスラブアロケーターを使用します)。つまり、それはメモリのブロックへの単なるポインタです。

MappedByteBufferは、mmap呼び出しを使用して割り当てられたメモリのセクションを表します。これは、メモリマップドI/Oを実行するために使用されます。したがって、MappedByteBuffersは、DirectByteBufferと同じようにメモリの使用を登録しません。

したがって、どちらもJVMの外部のメモリを表すという点で「直接」ですが、目的は異なります。

余談ですが、reservedMemory値を取得するために、JVMの内部メソッドを反射的に呼び出しています。このメソッドの実装は仕様でカバーされていないため、その値が何を返すかについての保証はありません。直接ByteBufferは、C / C ++からのNewDirectByteBuffer呼び出しを使用してJNI内から割り当てることができ(MappedByteBuffersはこれを使用する可能性があります)、これはおそらくreservedMemory値に影響しません。これは、JavaByteBuffer.allocateDirectを使用する場合にのみ変更できます。

于 2009-08-05T07:25:23.403 に答える