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 は前方互換性がある」と主張しています。それは成功しましたか?
これらの問題に関するガイダンスをいただければ幸いです。(そしてねえ、これをすべて読んでくれてありがとう!)
編集
私の質問はかなり長くなったので、すべての詳細を述べませんでした。ウィルのコメントに対処するには:
- extern "C" 関数を呼び出すだけです。(たとえば、javah を使用して C ヘッダー ファイルを生成します。)
- JVM で C++ ランタイムを操作する必要はありません。(基本的には、文字列を C++ ライブラリに送信する必要があるだけです。)