15

Java Native Interface (JNI) は C++ ABI の互換性の問題の影響を受けますか?

私はJavaアプリケーションを開発しています。Java Native Interface (JNI) を使用して C++ ライブラリの関数を呼び出したいと考えています。C++ ライブラリのコードにアクセスできるので、必要に応じて再構築できます。(たとえば、C++ ランタイムを静的にリンクできます。)

ユーザーに JRE 6 以上を要求することはできますが、特定の C++ ランタイムを要求することはできません。

同僚がこのブログ記事を指摘してくれました: http://www.trilithium.com/johan/2005/06/static-libstdc/動的にロードされた C++ コードを使用しないようにアドバイスしています。

別の同僚がこのバグ レポートを指摘してくれました: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590には、これらの問題が Java 1.4.2 でどのように対処されたかが詳しく説明されています。

問題の要点は、私が理解しているように、libstdc++ のバイナリ インターフェイスが頻繁に変更されることです。C++ アプリケーションが別のコンパイラでビルドされた C++ 共有ライブラリをロードすると、互換性のない 2 つの libstdc++ ライブラリが同時にメモリにロードされます。

バグ レポートでは、Java 1.4.2 の解決策について説明しています。ネイティブ コードが C++ ランタイムを呼び出す必要がある場合、呼び出しは適切な libstdc++.so で解決されます。まだ 2 つの libstdc++.so が同時にロードされていますが、問題はありません。"

これについていくつか質問があります。

まず、OpenJDK はこのアプローチを採用し続けますか?

[編集: OpenJDK の build-dev メーリング リストでこの質問をしました。答えはイエスです。HotSpot は依然として libstdc++ を静的にリンクしていますが、明らかに「ほとんどの Linux ディストリビューションはこれにパッチを当てています」。別の開発者は、これにはパッチさえ必要ないと指摘しています:「STATIC_CXX=false を設定するだけで十分です (デフォルトは true)。」]

次に、この場合でも、互換性のない 2 つの libstdc++.so を同時にロードすることは本当に問題ないのでしょうか?

第三に、このアプローチ (JDK でシンボルを非表示にする) は、すべての互換性の問題に対処していますか?

上記のブログ記事では、「異なる ABI に対してコンパイルされたコードは、バイナリ互換性がない」と警告しています。そしてその後、「言語ランタイムのサポートは通常、共有されているデータに依存しています。たとえば、ある種のロックまたはグローバルデータ構造にアクセスするためです (C プログラムが共有 errno を必要とする方法と同様です)。」

これは、問題を解決できないように聞こえます。

もう一度言いますが、ABI の非互換性はもはや問題ではありません。ブログ記事は6年以上前のものです。別のスタックオーバーフローの質問 ( GCC ABI 互換性) に対する 1 つの回答は、「gcc-3.4.0 以降、ABI は前方互換性がある」と主張しています。それは成功しましたか?

これらの問題に関するガイダンスをいただければ幸いです。(そしてねえ、これをすべて読んでくれてありがとう!)

編集

私の質問はかなり長くなったので、すべての詳細を述べませんでした。ウィルのコメントに対処するには:

  1. extern "C" 関数を呼び出すだけです。(たとえば、javah を使用して C ヘッダー ファイルを生成します。)
  2. JVM で C++ ランタイムを操作する必要はありません。(基本的には、文字列を C++ ライブラリに送信する必要があるだけです。)
4

1 に答える 1

5

知らない。しかし、それは私を止めませんでした。

まず、それはあなたが何をしたいかによります。JDKの静的リンクの背後にある前提は、実際のJDK自体の移植性を向上させることです。ユーザーが特定のOSでJDKを再コンパイルすることを期待できないため、最終的なバイナリを移植可能にするメカニズムが必要でした。どうやら静的リンクはこの問題を修正しました。

次に、JNIに関しては、最初にC ++ではなくC関数を呼び出すことになりますが、JNIにはC++バインディングはないと思います。したがって、使用するC ++はすべて、Javaと通信するためにCルーチンでラップする必要があります。

次に、C ++ .soは、私が推測している通常のように、OSに対して動的にリンクします。JNIルーチンが動的にリンクされた.soで機能しないことを期待するのはかなり厳しいように思われ、C++.soも例外ではありません。そして、間違いなくC ++はそれなりに人気がありますが、C++.soに対して動的にリンクすることはできないということも同様に厳しいようです。したがって、これを容易にするために必要なシェナニガンが何であれ、They(tm)がこれを可能にするための作業を行ったというのは合理的な仮定です。

とは言うものの、使用しているC++がJavaランタイムのC++ランタイムと相互作用するという期待は確かにありません。理想的には、それらは単に平和的に共存します。

これがまったく機能すると仮定すると、C ++は動的にリンクされ、OSにインストールされているC ++ランタイムに翻弄されるため、ABIの移植性の問題が発生する可能性があります。

だから、結局、私はそれに裂け目を与えて、何が起こるかを見るでしょう。

于 2012-01-04T05:25:21.843 に答える