質問

カスタムクラスローダーがあるため、デスクトップアプリケーションは、対話する必要があるAppServerからクラスのロードを動的に開始できます。これを行うのに必要な瓶の量はばかげているので(これを出荷したい場合)、これを行いました。また、実行時にAppServerライブラリからクラスを動的にロードしないと、バージョンの問題が発生します。

今、2つの異なるAppServerと通信する必要があるという問題が発生しました。最初にロードするクラスによっては、ひどく壊れる可能性があります...実際に強制終了せずにクラスのアンロードを強制する方法はありますかJVM?

これが理にかなっていることを願って

役に立ちましたか?

解決

クラスをアンロードできる唯一の方法は、使用するクラスローダーがガベージコレクションされている場合です。つまり、すべてのクラスとクラスローダー自体への参照は、dodoの方法で行う必要があります。

あなたの問題の1つの可能な解決策は、すべてのjarファイルにクラスローダーを持ち、特定のJarクラスローダーにクラスの実際のロードを委任するAppServerのそれぞれにクラスローダーを持つことです。そうすれば、すべてのAppサーバーに対して異なるバージョンのjarファイルを指定できます。

しかし、これは簡単なことではありません。 OSGiプラットフォームは、各バンドルに異なるクラスローダーがあり、プラットフォームによって依存関係が解決されるため、まさにこれを実行しようとします。たぶん良い解決策はそれを見てみることでしょう。

OSGIを使用したくない場合、可能な実装の1つは、 JarClassloader クラス。

そして、Classloaderを拡張する新しいMultiClassloaderクラスを作成します。このクラスは内部的にJarClassloaderの配列(またはリスト)を持ち、defineClass()メソッドでは、定義が見つかるか、NoClassDefFoundExceptionがスローされるまで、すべての内部クラスローダーを繰り返し処理します。クラスに新しいJarClassloaderを追加するために、いくつかのアクセサーメソッドを提供できます。 MultiClassLoaderのネット上にはいくつかの実装が考えられるため、独自に作成する必要さえないかもしれません。

サーバーへの接続ごとにMultiClassloaderをインスタンス化する場合、原則としてすべてのサーバーが同じクラスの異なるバージョンを使用する可能性があります。

プロジェクトでMultiClassloaderのアイデアを使用しました。ユーザー定義スクリプトを含むクラスをメモリからロードおよびアンロードする必要があり、非常にうまく機能しました。

他のヒント

はい、クラスをロードして「アンロード」する方法があります。それらは後で。トリックは、高レベルのクラスローダー(システムクラスローダー)とアプリサーバーのクラスローダーの間に存在する独自のクラスローダーを実装し、アプリサーバーのクラスローダーがクラスローディングを上位ローダーに委任することを期待することです。 。

クラスは、パッケージ、名前、および最初にロードしたクラスローダーによって定義されます。 「プロキシ」をプログラムするJVMの起動時に最初にロードされるクラスローダー。ワークフロー:

  • プログラムが起動し、実際の「メイン」クラスがこのプロキシクラスローダーによってロードされます。
  • 通常ロードされるすべてのクラス(つまり、階層を壊す可能性のある別のクラスローダー実装を介さない)は、このクラスローダーに委任されます。
  • プロキシクラスローダーは、 java.x および sun.x をシステムクラスローダーに委任します(これらは システムクラスローダー)。
  • 交換可能なすべてのクラスについて、クラスローダー(実際にクラスをロードし、親クラスローダーに委任しない)をインスタンス化し、これを介してロードします。
  • クラスのパッケージ/名前をキーとして、クラスローダーを値としてデータ構造(つまり、ハッシュマップ)に保存します。
  • プロキシクラスローダーは、以前にロードされたクラスのリクエストを取得するたびに、以前に保存されたクラスローダーからクラスを返します。
  • クラスローダーによってクラスのバイト配列を特定し(またはデータ構造からキーと値のペアを「削除」し)、変更する場合にクラスをリロードするだけで十分です。
  • li>

完了したら、 ClassCastException または LinkageError など

>

クラスローダー階層の詳細については(はい、ここで実装しているものです;-) &quotをご覧ください。 ;サーバーベースのJavaプログラミング"テッド・ニューアード-この本は、あなたが望むものに非常に似たものを実装するのに役立ちました。

カスタムクラスローダーを作成しました。このクラスローダーから、クラスローダーをGCせずに個々のクラスをアンロードできます。 ジャークラスローダー

クラスローダーは厄介な問題になる可能性があります。複数のクラスローダーを使用しており、それらの相互作用が明確かつ厳密に定義されていない場合、特に問題が発生する可能性があります。実際にクラスをアンロードできるようにするには、アンロードしようとしているクラス(およびそのインスタンス)へのすべての参照を削除する必要があります。

この種のことを行う必要があるほとんどの人は、 OSGi を使用することになります。 OSGiは本当に強力で、驚くほど軽量で使いやすい、

ClassLoaderはアンロードできますが、特定のクラスをアンロードすることはできません。具体的には、管理下にないClassLoaderで作成されたクラスをアンロードすることはできません。

可能であれば、アンロードできるように独自のClassLoaderを使用することをお勧めします。

クラスには、ClassLoaderインスタンスへの暗黙の強い参照があり、その逆も同様です。これらは、Javaオブジェクトと同様にガベージコレクションされます。ツールインターフェースなどを使用しないと、個々のクラスを削除できません。

これまでどおり、メモリリークが発生する可能性があります。クラスまたはクラスローダーのいずれかへの強い参照は、すべてをリークします。これは、SunのThreadLocal、java.sql.DriverManager、java.beansなどの実装で発生します。

JConsole など、クラスのアンロードロジックの最後に java.lang.System.gc()を追加してみてください。ガベージコレクターを明示的にトリガーします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top