web-dev-qa-db-ja.com

静的ライブラリとJNIのリンク

以前のJavaバージョンJava 8では、共有ライブラリにネイティブコードが存在する必要がありますが、Java 8で静的リンクライブラリを使用することが可能ですJNI。例を検索しましたが、見つかりませんでした。

JavaアプリケーションにJNIライブラリを静的にリンクするにはどうすればよいですか?

17
chmod

Java SE 8仕様は静的リンクをサポートするように変更され、静的リンクはJDKで実装されています。これは System.loadLibrary の仕様で簡単に説明されています。それが参照するJNI仕様のセクションは here および here です。

ネイティブメソッドシグネチャとデータ型は、静的および動的にリンクされたメソッドで同じです。ただし、ライブラリを静的にリンクするには、JDKメイクファイルをハックする必要がある場合があります。

大きな違いの1つは、静的ライブラリの初期化方法です。動的ライブラリは、_JNI_OnLoad_関数を呼び出して初期化され、_JNI_OnUnload_を呼び出して初期化解除されます。各動的ライブラリは、これらの関数の独自のバージョンを持つことができます。静的にリンクされたライブラリが複数ある場合、それらすべてに同じ名前の関数を含めることはできません。 libnameという名前の静的ライブラリの場合、ロード/アンロード関数は_JNI_OnLoad_libname_および_JNI_OnUnload_libname_です。

_JNI_OnLoad_libname_関数は、_JNI_VERSION_1_8_以上の値を返す必要があります。そうでない場合、JVMは静的ライブラリを無視します。

基本的に、System.loadLibrary("foo")を呼び出すと、システムは実行中の実行可能イメージで関数_JNI_OnLoad_foo_を探し、見つかった場合は、ライブラリが静的にリンクされていると想定し、そのネイティブメソッドが検索されます実行中のイメージ内。 _JNI_OnLoad_foo_が見つからない場合、通常の検索と動的ライブラリの読み込みが行われ、見つかった動的ライブラリからネイティブメソッドがリンクされます。

11
Stuart Marks

コメントでリンクしたJEP 178に従って、別のことをする必要はありません。 System.loadLibraryは、動的ライブラリと静的ライブラリの両方をロードします。

動的なネイティブライブラリではなく静的なネイティブライブラリを使用するために、既存のJavaコードに変更を加える必要はありません。特に、System.loadLibrary( "foo")という形式のメソッド呼び出しは、ライブラリが静的形式で提供されるか動的形式で提供されるかに関係なく、「foo」ライブラリをロードできる必要があります。

おそらく、Java.library.pathが正しく設定されていることを確認する必要があるだけです。

3
dkatzel

Java 8の拡張 https://openjdk.Java.net/jeps/178 は、JVM向けです。

2つのファイルがあるとします。

  • Main.Java
  • Main.c

Libnative.soを作成します。

javac Main.Java
javah Main
gcc -c Main.c
gcc -c Main.c -I /home/dx/.sdkman/candidates/Java/current/include/linux -I /home/dx/.sdkman/candidates/Java/current/include
gcc -shared -o libnative.so Main.o

Libnative.aを作成します。

ar -cvq libnative.a Main.o

Libnative.a、libnative.soのテストごとに、以下を実行します。

Java -Djava.library.path=.  Main

結果:

  • libnative.soが成功した場合
  • libnative.aのときに実行が失敗する

これは、178がJVM用であることを証明しています。

参照:

0
typelogic