質問

MappedByteBuffer を使用して特定のファイルをメモリマッピングすることにより、2つ以上のJVM間で一種の共有キャッシュを実装しようとしました。仕様から、 MappedByteBuffer.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. 上記のコードの出力は、Direct Memory Usageの場合は0バイトです(File.txtは1 GB)。しかし、行のコメントを外すと..

    ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);
    

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

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

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

ありがとう!

役に立ちましたか?

解決

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

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

つまり、両方とも「直接」ですがJVMの外部のメモリを表すという点で、目的が異なります。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top