2016-03-27 19 views
3

ライブラリファイルをsystem.loadLibrary()関数を使用してロードした直後にライブラリファイルを削除することはできますか?ここにシナリオがあります...JVMにロードした後の一時ファイルの削除

私たちはJavaアプリケーションから呼び出すためにC言語で書かれたDomainSocketユーティリティを使用するためにJNIを使​​用しています。 .SOファイルを同じjarにパッケージングし、ユーティリティを使用してファイルシステム上に一時ファイルを作成し、loadLibrary関数を使用して.SOをロードします。一意の一時ファイルを作成するFile.createTempFile()を使用しています。 deteleOnExit()を使用して、JVMのシャットダウン時に一時ファイルを削除しています。

JVMのスタンドアロンアプリケーションでは、これは問題なく動作します。しかし、同じJVM上で複数のアプリケーションを実行できるので、TomcatのようなWebコンテナにデプロイするときに問題があります。まず、展開された各アプリケーションごとに一時ファイルが作成されます。本当の問題は、Appが停止して起動または再デプロイされたときに、一時ファイルが削除されずに新しいファイルが作成されることです。 JVMがシャットダウンすると、すべての一時ファイルが削除されます(Tomcatが再起動されます)。

loadLibrary()の後に一時ファイルを削除する方法を試しました。これはうまくいくようです。再起動時に新しい一時ファイルが作成され、ロード直後に削除されます。

誰かがポインタ/提案を持っているかどうか確認したいと思っていましたか?

これらの.SOファイルをアプリケーションの一部にしたいので、common/libメカニズムを使用して.SOファイルをコンテナごとに一度だけロードすることは望ましくありません。

答えて

0

ライブラリファイルをsystem.loadLibrary()関数を使用してロードした直後に、ライブラリファイルを削除しても問題ありませんか?

いいえ。 OSはいつでもライブラリを「アンロード」することができ、バイナリをディスクから再ロードする必要があります。ファイルを削除すると(実際にプロセスによって保持されているわけではない)、おそらく "BUS ERROR"や他のほとんど説明できない状態のような非常に奇妙な動作が発生します。

ライブラリがメモリから落とされずにディスクから再ロードされていない場合でも、さまざまなOSに「レイジーローディング」などのフラグが付いているため、ディスクライブラリのアーティファクトがすべてのコードが実際にそこからロードされる前に。

一意の一時ファイルを作成するFile.createTempFile()を使用しています。 deleteOnExit()を使用して、JVMのシャットダウン時に一時ファイルを削除しています。

これは遭遇している問題を除いて、妥当なアプローチのようです。 File.createTempFileを使用する代わりに、予測可能なファイル名(たとえば/tmp/libgoodstuff.so)を予測可能な場所に使用してみませんか?これを行うと、ロードするライブラリごとに1つのファイルを作成(および削除のスケジュールを立てる)するだけで済みます。

[I]誰かがポインタ/提案を持っているかどうかを確認したいと思いますか?

アプリケーションに.soファイルを配置することは、ターゲット環境を非常にうまく理解しない限り、管理するのが難しくなります。たとえば、ターゲットアーキテクチャとOSが正しいかどうかを確認する必要があります。

最終的に、配布可能なアプリケーションの一部としてのネイティブライブラリは、Javaを使用したネックの痛みであり、他のオプションがない限り避けるべきです。

+0

ライブラリをいつでもアンロードできると言ったときに、どのOSを参照していますか? – apangin

+0

@apangin私が気にしていた特定のOSはありません。しかし、POXIXなどのコードはロードされず、ディスクベースのアーティファクトは自由に消えるという要件はありません。私は、 "定義されていない動作"がロードされた結果、ディスクから共有ライブラリを削除した結果と期待します。 –

+0

さて、共有ライブラリが削除されたときにアプリケーションがクラッシュする原因となるOS(少なくともOracle JDKでサポートされているOS)はわかりません。通常、OSは削除を拒否(Windows)するか、ファイルのデータをディスクに保存したままファイル名のリンクを解除(Linux)します。ファイルを削除しても、すでに開いているこのファイルのメモリマッピングには影響しません。 – apangin

0

はい、この方法が有効ですが、特定の制限があります。

System.loadLibraryが呼び出されると、対応する.soファイルがプロセスアドレス空間にmmap-edされます。ファイルを削除すると、対応するdentryはすぐに削除されますが、inodeは削除されません。つまり、ファイル名はリンクされていませんが、ファイルへの最後の参照が解放されるまでファイルデータは保持されます。

これは、パッケージマネージャが更新プログラムをインストールする方法です。実行中のプロセスで使用されている場合でも、実行可能ファイルと共有ライブラリは削除されることがあります。 OSは実行中のプログラムが古いバージョンのライブラリを使用し続けることを保証し、新しいプログラムは新しいバージョンをロードします。

ただし、この方法は移植性がありません。 Linuxでは動作しますが、他のOSではなく、すべてのファイルシステムで動作します(WindowsやFATなど)。したがって、特定のOSプラットフォームが使用されていることが分かっている場合を除き、私はそうすることをお勧めしません。

+0

Webコンテナ内に1つの.SOファイルだけで不具合が発生しました。あるWebアプリケーションによってロードされた.SOファイルは、クラスローダーのために別のWebアプリケーションによってロードできません。 Tomactは各Webアプリケーションに一意のクラスローダーを割り当て、*同じ* .SOの複数の読み込みは機能しません。 – user2089210

+0

@ user2089210そう、私はその部分を逃しました。したがって、アプリケーションがプラットフォーム間で移植可能である必要がない場合、ライブラリがロードされるとすぐにライブラリを削除することができます。まあ、JNIライブラリを持っていると、アプリケーションはポータブルになりません。 – apangin

関連する問題