16

Java でこれを尋ねるのは奇妙な質問だと思いますが、Java の動的メモリ割り当てをいくつかの配置制約に合わせる方法はありますか? たとえば、ページ サイズに合わせてオブジェクトを動的に割り当てることは可能ですか?

これを行う理由は、JNI インターフェイスを介してネイティブ コードから Java オブジェクトにアクセスするためであり、ネイティブ コード ライブラリではオブジェクトを整列させる必要があります。

ありがとう。

4

3 に答える 3

8

いいえ、できません。Java のヒープ上のオブジェクトは、ガベージ コレクション中に移動できることに注意してください。いくつかのオプションがあります:

  1. JNI から直接 Java オブジェクトにアクセスするのをやめます。関心のあるものを、ネイティブ コードが既に整列している JNI 提供のバッファにコピーします。
  2. ByteBuffer.allocateDirect()を使用します。次に、正しく配置されたバッファーの領域を見つけます。これを行う 1 つの方法は、起動時にバッファーを割り当て、動作するまで、さまざまなオフセットでアラインメントに依存する操作を繰り返し試行することです。これはハックです!
于 2011-03-11T02:01:40.803 に答える
5

このブログ投稿を参照して、要件もカバーする Java でのダイレクト メモリ アラインメントのより広い議論を参照してください。要約する:

  1. JDK 1.6 までは、すべてのダイレクト バイト バッファはページ整列されているため、それが使用している Java のバージョンである場合、ソートされます。
  2. 1.7以降は自分で、投稿で概説されている方法に従って、整列されたバッファを取得してください。

適切なアドレスに到達するまで、割り当てを繰り返さないことをお勧めします。これは、ソフトウェアにとって非常に悪いことです。アドレスを繰り返し取得する予定がある場合、上記のリフレクション メソッドを使用する予定がある場合は、アドレスをキャッシュすることをお勧めします。または、投稿で概説されている方法を使用して Unsafe を使用し、アドレス フィールドの値を取得します。

于 2013-01-08T15:08:15.780 に答える
2

美しいオプションはないので、醜いオプションを次に示します。

Sun (現在は Oracle) JRE 5.0 または 6.0 を使用している場合は、次を使用できます。

   ByteBuffer buffer = ByteBuffer.allocateDirect(pageSize);
   Method getAddress = buffer.getClass().getMethod("address");
   long address = getAddress.invoke(buffer);
   // and now send address to JNI

Java でデータにアクセスするには、bufferを使用します。JNI でアクセスするには、アドレスをポインタにキャストします。どちらも同じデータを表示/変更します。

アドレスはページ境界で整列されているはずですが、それを確実にするために、2 つのページを割り当てることができます (完全に整列されたページに対して十分なスペースがあるはずです)。次に、ページ上のアドレスを揃えて、オフセットを ByteBuffer アクセスに適用します。

任意の VM で機能するバッファー割り当てとネイティブ呼び出しの別のオプションは、JNAs メモリ クラスを使用することです: http://jna.java.net/javadoc/com/sun/jna/Memory.htmlcom.sunパッケージで怖がらないでください。オープンソースであり、LGPL です。

于 2011-03-11T02:18:01.327 に答える