レガシーC++コードのデータとメソッドにアクセスするためにJNI呼び出しを行う必要があるTomcat 3.2.1で実行されているWebアプリケーションがあります。サーブレットはWebアプリケーションの起動時にロードされ、そのinit
メソッドの一部として、そのWebアプリケーションインスタンスに固有のデータセットがC++データ構造にロードされます。
このJavaコードには以下が含まれます:
static
{
try {
System.loadLibrary("JCoreImpl");
System.out.println("JCoreImpl loaded");
m_bLibraryLoaded = true;
} catch (UnsatisfiedLinkError e) {
m_bLibraryLoaded = false;
System.out.println("JCoreImpl NOT loaded " + e);
}
}
Webappが1つしかない場合は問題なく動作します(「webapps/aaa」と呼びましょう)。
C++データ構造で使用されるデータセットを除いてwebapps/aaaと同じ2番目のwebapp( "webapps/bbb")がある場合、webapps/aaaは問題なく起動しますが、webapps/bbbを起動すると次のことを示すエラー:
JCoreImpl NOT loaded Java.lang.UnsatisfiedLinkError: Native Library
E:\WebStation\binDebug\JCoreImpl.dll already loaded in another classloader
各インスタンスにはその特定のWebアプリに固有のデータが含まれている必要があるため、Webアプリケーションごとにネイティブライブラリの個別のインスタンスを用意する必要があります。メールアーカイブを検索し、クラスローダーの階層を説明するクレイグマクラナハンのメールを読みました。しかし、各Webアプリのネイティブライブラリの一意のインスタンスをロードすることに固有のものを見つけることができませんでした。
同じネイティブライブラリを2回ロードすることはできません。
クラスを<Tomcat>/lib/
の下のjarファイルに入れます。これは、すべての戦争で共有されます。
Tomcat HowTo wikiのセクション TomcatでJNIを使用するとクラスローダーの問題が発生します を参照してください( http://wiki.Apache.org/Tomcat/HowTo )
私はこの問題を抱えていて解決しました:
問題:
この問題は、アプリケーションサーバーの構成によって、複数のwar
またはear
ファイルが作成され、その結果、複数のデプロイ済みファイルが作成されることが原因です。これらのデプロイされたファイルは、静的ブロックにロードされたネイティブライブラリへの同時アクセスを試みます。
ソリューション:
Java
プロセスを完了しますjboss-eap-6.4.0\standalone\configuration
そして開くstandalone.xml
ファイルstandalone.xml
、deployments
タグをすべて削除します(心配しないでください。アプリケーションサーバーを再実行すると、このタグが挿入されます。jboss-eap-6.4.0\standalone\deployments
と展開されたすべてのファイルとwar
ファイルを削除します。 (warファイルをバックアップできます)exploded
である必要がある新しいデプロイメントを追加しますDLLをロードする前に、一時ディレクトリ内の一時ファイルにDLLをコピーします。完了したらファイルを削除します。このようにして、同じDLLが2回ロードされないようにすることができます。