Javaでは、クラスは特別なオブジェクトであるクラスローダーによってメモリに読み込まれます。各クラスローダーは独自のクラスの可視性スペースを形成します。
クラスローダーの種類:
$JAVA_HOME/lib/extから拡張を読み込みます。特徴:
同じクラスの異なるバージョンをJVMプロセスに読み込むことはできますか?それをどうやって行いますか?
答え: はい、異なるクラスローダーを使用すれば可能です。同じFQDNのクラスは異なるローダーによって読み込まれると、JVMにおいて異なるタイプと見なされます。
例:
ClassLoader loader1 = new URLClassLoader(new URL[]{...}); ClassLoader loader2 = new URLClassLoader(new URL[]{...}); Class clazz1 = loader1.loadClass("com.example.MyClass"); Class clazz2 = loader2.loadClass("com.example.MyClass"); System.out.println(clazz1 == clazz2); // false
物語
大規模なサーバーシステムで、各プラグインが別々のカスタムクラスローダーを介して接続されていました。プラグインは共通インターフェースを介してオブジェクトを交換しましたが、そのインターフェースも自身のクラスローダーによって読み込まれていました。
ClassCastExceptionが発生しましたが、これはプラグインのクラスローダーとメインシステムのインターフェース 'PluginApi'が異なるタイプと見なされたためです。
物語
カスタムクラスローダーを介したサーブレットの"ホット"再読み込みの試みはメモリリークを引き起こしました — 古いクラスがメモリから排出されず、静的変数にどこかで参照が残っていました。結果として、PermGenはすぐに溢れました。
物語
動的モジュール読み込みをサポートする製品がシステムクラスローダーを暗黙的に使用していましたが、開発者が親を間違って置き換え、基本クラス(例えばJDKのもの)へのアクセスを失いました。新しいモジュールが標準のJavaクラス(例えば
java.sql.Driver)を読み込むことができない場合の障害として現れました。