読み書きソケットやファイルは、ネイティブのメモリを使うのか?

紳士:

最近、私はJVMの詳細にされていると用語遭遇したダイレクト・メモリを以下からの回答@Peter Lawreyは私の注意を握っ。

すべてのシステムは、ソケットやファイルの読み書きとして呼び出すネイティブのメモリを使用するだけ彼らは、ヒープを使用することはできません。


私の質問

  1. これは本当ですか?
  2. どれでも私はこの文を照合することができますどこ?
  3. 内の任意の呼び出しを意味しているのはNIO、私は直接使用するダイレクト・メモリを
フロリアンWeimerさん:

ソケット転送(及びシステムコール)でヒープメモリ対ネイティブ

から、ソケットへのデータ転送のみをネイティブ(非ヒープ)メモリを使用することができるというのは本当ではありません。これは、JVMの実装に完全に依存し、さらには時々同じ実装内で変化させることができます。

実際には、JNI直接ヒープメモリを使用する機能や回避のコピーを書くことは非常に容易です。JNIのAPIは、Javaヒープ内のデータへのゼロコピーにアクセスするためのメソッドを提供します。

バイト配列を扱うときに、第2の1は非常に便利です。

ガベージコレクションとの相互作用

これらのJNI関数は進展してから、ガベージコレクションを防ぐこと多くの場合、コピーを作成することがより有益です。(例えばカーネルがリターンにデータをバッファリングしていることを確実に知られていないときにTCPソケットからの読み取りなど)ブロッキングシステムコールを行うとき、これは特にそうです。他の場合には、長いストール回避するために、より小さな断片に、増分アレイを処理することが可能であってもよいし、コピーの必要性。

これらの課題のために、OpenJDKの11における現在の実装ではなくてもブロッキングがカーネル内で発生しないであろう場合には、およびヒープに割り当てられた(非直接)バイトバッファからゼロコピー転送を試みないとへの影響はないだろう無限の遅延に起因するガベージコレクション。

直接バイトのバッファを使用するための禁忌

NIOとの直接バイトバッファを使用すると、さまざまな問題があります。これらのバッファは、ファイナライズのいくつかの並べ替えを必要としています。その結果、ガベージコレクタは、のように効率的にそれらを配置することができない(かつ迅速に)他のオブジェクトとして。一般的に、(例えば、それらが使用されると、チャネルと共に割り当て)長寿命されている場合にのみ直接バイトバッファを使用することが賢明です。一時的なバッファに、アレイ・バックバッファ(またはプレーンアレイが)ほとんどの時間よりも優れています。

OpenJDKの実装は、透過チャネルの転送のためにそれらを使用して、将来の使用のためのスレッドごとのキャッシュに戻し、現在のスレッドに直接バッファを関連付けることによって、この問題を回避することができます。このように、ダイレクトバッファは常に割り当てられ、破棄されていません。

古いOpenJDKのリリース

クリティカルセクションの配列アクセス機能は、Java 1.2に戻る上記の。個々の仮想マシンとガベージコレクション実装はまだ一時的なコピーを作成するかどうか(インタフェースを慎重にコピーを回避することはそれらを実装する必要はないように設計されています)もちろん、不特定です。OpenJDKの8でのホットスポットでは、これらのJNI関数は決してコピーを作成しませんが、アレクセイShipilёvの記事で説明したように、ガベージコレクションの影響はコレクタにコレクタによって異なります。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=203920&siteId=1