2

私は、メモリ マップされたファイルを介してアクセスできる小さくてシンプルなストレージ システムを使用しています。2GB を超えるスペースに対処する必要があるため、2GB のような固定サイズの MappedByteBuffer のリストが必要です (さまざまな理由で使用量を減らしています)。次に、すべてが比較的単純です。バッファは1GBなどの特定のスペースにマップされ、さらに必要な場合は新しいMappedByteBufferをマップし(ファイルは自動的に増加します)、さらに必要な場合は3番目のバッファがマップされます。これはうまくいきました。

しかし、その後、ファイルの長さを変更すると問題が発生する可能性があることをJava NIO の本で読みました。

MappedByteBuffer は、関連付けられているディスク ファイルを直接反映します。マッピングが有効な間にファイルが構造的に変更されると、奇妙な動作が発生する可能性があります (正確な動作は OS とファイル システムに依存します)。具体的には、マッピングが有効な間にファイルのサイズが変更された場合、バッファーの一部またはすべてにアクセスできなくなったり、未定義のデータが返されたり、未チェックの例外がスローされたりする可能性があります。ファイルがメモリ マップされている場合、他のスレッドまたは外部プロセスによってファイルがどのように操作されるかに注意してください。

ファイルが増加しているときにOSがファイルを移動し、MappedByteBuffersが無効なスペースを指す可能性があるため、問題が発生する可能性があると思います(または、これを誤解していますか?)

そのため、新しい MappedByteBuffer をリストに追加する代わりに、次のことを行っています

  1. ファイルの長さを増やす
  2. バッファ リストをクリアします (古いバッファを破棄し、ガベージ コレクタを介してバッファが解放されることを期待します。うーん、おそらく、cleaner.clean() を介して明示的にすべてのバッファをクリーンアップする必要がありますか?)
  3. 再マッピング (リストを新しいバッファーで埋める)

しかし、この手順には、マッピング中に時々失敗するという欠点があります

IOException: Operation not permitted
    at sun.nio.ch.FileChannelImpl.map0(Native Method)
    at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:734)

どうして?バッファリストをクリアしてもバッファが適切に解放および消去されず、複数のマッピングが許可されていないためですか? 本のコメントを無視して、古い作業方法に固執する必要がありますか?

アップデート

  • 32 ビット OS でマッピングを分割すると、空き領域を見つけやすくなり、エラーが発生しにくくなるという利点があります ( ref )
  • mmap の設定にはコストがかかる可能性があるため、マッピングを小さな部分に分割することは利点です ( ref ) 。
  • どちらのアプローチもクリーンではありませんが、2 番目のアプローチは機能するはずですが、マップを解除する必要があります (通常の cleaner.clean ハックで強制的にリリースしようとします)。最初のアプローチは、ファイルサイズを増やすことができるシステム(ibmなど)で機能するはずですが、正確な理由はまだわかりませんが、一般的には機能しません...
  • 最もクリーンな方法は、私が恐れている複数のファイルを使用することです(MappedByteBufferごとに1つのファイル)
4

1 に答える 1

1

根本的な原因は私のせいでした: 誤って基になるファイルを頻繁に再マップしました (容量は小さな手順でのみ増加しました)。

しかし、この極端な状況でも、失敗したマッピング操作 (+ System.gc + a 5ms sleep -> jvm にバッファーのマップを解除する機会を与える必要があります) を再試行していたときに、最終的に IOException (操作が許可されていません) を修正することができました。 . 現在、最終的な結論につながる膨大な数の再マッピングしか見られませんでした。

少なくとも、mmap についてもう少し学びました。これは、OS とファイルシステムに非常に依存しています - auselenにも感謝します! クリーンなソリューションが必要な場合は、最初に彼から提案されたように、ファイルごとに 1 つの MappedByteBuffer を使用する必要があります。ただし、大きなスペースが必要で、OS ファイル記述子の制限が低すぎる場合、これも問題になる可能性があります。

最後になりましたが、ファイル サイズの増加後にマップされたバッファーをそのままにしておく保証 (IBM OS のみ ;)) を見つけることができなかったため、最初のソリューションに対して強くお勧めします。

于 2012-12-23T22:15:56.230 に答える