4

-Xmsおよびオプションを使用すると-Xmx、メモリ割り当てプールの初期サイズと最大サイズを設定できます。私が見つけたLinuxとAIXでstrace/trussを使用すると、JVMは内部で(k)mmapシステムコールを使用します。アドレス-ParameterはNULLであるため、オペレーティングシステムは、メモリをマップする仮想メモリアドレスを決定します。

$ truss java -Xmx512M Hello 2>&1 | grep mmap
kmmap(0x00000000, 536870912, 3, 17, -1, 0x00000000, 0x00000000) = 0xB0000000

このアドレスを指定することは可能ですか?

背景:Java Native Interface(JNI)を介してレガシーコードを呼び出す必要があります。これには、メモリ内の特定の場所にマップされた大量の再配置不可能なデータ(32ビットアドレス空間で2 GB)が必要です。この領域は、Javaのメモリ割り当てプールの場所と重複しています。

編集:これは実際のメモリレイアウトです:

0x0... AIX
0x1... Text
0x2... Stack
0x3... Heap
0x4... Heap
...... Legacy Data (2 GB)
0xd... Shared Library Text
0xe... unused
0xf... Shared Library Data

私の目標は、Javaメモリ割り当てプールを0xb/0xcから0x3/0x4セグメントに移動することです。これは、標準(非大容量)メモリモデルでも使用できます。

4

3 に答える 3

2

個人的には、割り当てプールアドレスを設定する方法を聞いたことがありません。そのような設定がある場合、それはおそらく非常にあいまいです。

確認する唯一の方法は、http://hg.openjdk.java.net/で入手可能なJDK/JREのソースを確認することですNULLパラメータがハードコーディングされている場合は、運が悪いです。

別の解決策として、誤動作したネイティブコードを修正できない場合は、次のようにします。

小さなネイティブプログラムを作成してネイティブコードを呼び出し、Javaから(を介してRuntime.exec)プログラムを呼び出すことができます。そうすれば、いたずらなコードは、個別のアドレススペースを持つ独自のOSプロセスを取得します。もちろん、これは、ネイティブコードとJavaの間を行き来することがあまりない場合にのみ実現可能です。

または、コードをJavaアプリと並行して実行される小さなサーバーにして、2つが通信できるようにします...

追記:

mmapのマンページで、アドレスの指定mmapが必ずしもサポートされていないことに気づきました。

MAP_FIXED:addrを正確に解釈します。[...]MAP_FIXEDをサポートするかどうかは実装によって定義されます。MAP_FIXEDは、XSI準拠のシステムでサポートされます。[...] MAP_FIXEDが設定されていない場合、実装はaddrを実装定義の方法で使用してpaに到達します。

http://linux.die.net/man/3/mmap

したがって、JVMmmapに特定のアドレスでの呼び出しを許可したとしても、それでも成功しない可能性があります。

于 2011-01-03T15:20:51.503 に答える
2

おそらく、この問題を裏返しにすることができます。ネイティブプロセスを開始し、交渉不可能なスペース(mmapなど)を予約するために必要なことを実行します。次に、Javaの呼び出しAPIを使用して、ネイティブプロセス内でJVMを作成して開始します。そのJVMがメモリ管理をどのように行うかについてのドキュメントは見つかりませんがホストプロセスによってすでに割り当てられているメモリ(ローカルmallocを使用していると思います)でうまく機能するのは当然です。ヒープを配置する場所が他に見つかります。0x3-0x4リージョンを未割り当てのままにしておくと、そこに配置されることを期待できます。

ただし、JVMのメモリモデルに十分なアドレス空間が残っていないという本当のリスクがあると思います。0x3-0x4リージョンは、何、512 MBですか?JVM全体(ヒープ、スタック、パーマ、VM構造など)をそこに収めることができれば問題ありませんが、そうでない場合は、JVMがヒープに連続したメモリを割り当てることができないと、非常に混乱することがあります。 。またはそうではないかもしれません。本当にわかりません。

したがって、これを提案したので、それを行わないことを強くお勧めします。代わりに、sleskeのアドバイスに従い、ネイティブコードを別のプロセスに配置します。

于 2011-01-03T17:52:36.083 に答える
1

試すことができるアイデアの1つは、LD_PRELOADを使用して独自のkmmap動作を注入することです。Googleは、 TCMallocプロジェクトにカスタムmallocを注入するためのLD_PRELOADの例を提供しています。

于 2011-01-03T16:47:47.913 に答える