JNI、ネイティブライブラリのロード。 その場でjava.library.pathを変更する

主にJNIに関連するJavaエコシステムのサブセット(Cか他の言語で記述された何らかのレガシーまたは単にまれで特定のコードと統合しなければならない場合、それなしでは行けません)には、javaのようなものがあります。 library.path。 要するに、これはクラスパスに多少似ていますが、Javaクラスと* .jarファイルではなく、ネイティブライブラリ-これらのネイティブライブラリ(Windowsの.dllまたはUnixの.so)を探す場所をJVMに指示するシステムプロパティです。

このプロパティは、JVMを起動する前に、グローバルシステムプロパティを介して、またはJVMの-Dname = valueスイッチとして一度設定され、その後読み取り専用になります。 より正確には、変更できますが、プログラムの動作には影響しません。 このプロパティを更新した後、JVMはそれを再読み込みせず、新しい値を使用しません。

カットの下-実行時にこのプロパティを変更する方法について、およびJavaでネイティブライブラリを実際にロードする方法について少し説明します。



ただし、java.library.pathをオンザフライで変更する機能は非常に便利です。そのため、たとえば、アプリケーションサーバーの起動前に必要なすべてのパスを反映するために、JBossを何度も実行するスクリプトを生成、書き換え、書き換える必要はありません。

また、JVMがネイティブライブラリを検索するこれらの方法を変更する機会があります。 具体的な手法はここ-blog.cedarsoft.com/2010/11/setting-java-library-path-programmaticallyに 、ここにはnicklothian.com/blog/2008/11/19/modify-javalibrarypath-at-runtimeに示されています。

ここで、ロードメカニズム自体について説明します。何らかの理由で、リンクによって説明されるものが機能することを説明します。 通常、ネイティブライブラリは静的イニシャライザを介してロードされます。

static {
try {
System.loadLibrary(«dp-integ»);
}
}


* This source code was highlighted with Source Code Highlighter .


これは次のようになります。

public static void loadLibrary( String libname) {
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
}


* This source code was highlighted with Source Code Highlighter .


さらに、Runtimeクラスで:

synchronized void loadLibrary0(Class fromClass, String libname) {
// ,
SecurityManager security = System.getSecurityManager();
if (security != null ) {
security.checkLink(libname);
}
if (libname.indexOf(( int ) File .separatorChar) != -1) {
throw new UnsatisfiedLinkError( "Directory separator" +
"should not appear in library name: " + libname);
}
ClassLoader.loadLibrary(fromClass, libname, false );
}


* This source code was highlighted with Source Code Highlighter .


つまり 最終的に、ネイティブライブラリは、通常のクラスと同様にClassLoaderを介してロードされます。 ClassLoaderクラスには、初期化された検索パスがキャッシュされる2つのプロパティがあります。

// The paths searched for libraries
static private String usr_paths[];
static private String sys_paths[];


* This source code was highlighted with Source Code Highlighter .


ClassLoader.loadLibraryメソッド(fromClass、libname、false)のコードは、非常に長く、多数のチェックが散らばっているので、短縮形ではこのように見えます。

// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
static void loadLibrary(Class fromClass, String name,
boolean isAbsolute) {

ClassLoader loader = (fromClass == null ) ? null : fromClass.getClassLoader();
if (sys_paths == null ) {
// ,
usr_paths = initializePath( "java.library.path" );

// , ,
// boot classpath.
sys_paths = initializePath( "sun.boot.library.path" );
}

// , ,
// , -
// Oops, it failed
throw new UnsatisfiedLinkError( "no " + name + " in java.library.path" );
}


* This source code was highlighted with Source Code Highlighter .


したがって、ネイティブライブラリのロードメカニズムがより明確になりました。

クラスローダーのsys_pathsプロパティをnullに設定するか、sys_paths / usr_pathsプロパティを変更して、必要なパスをネイティブライブラリに追加することができます。

Source: https://habr.com/ru/post/J118027/


All Articles