ProgrammingシニアJavaバックエンド開発者

Javaにおけるクラスローディングメカニズムはどのように機能し、クラスローダーの種類は何があり、誤った使用による問題は何ですか?

Hintsage AIアシスタントで面接を突破

答え。

Javaでは、クラスは特別なオブジェクトであるクラスローダーによってメモリに読み込まれます。各クラスローダーは独自のクラスの可視性スペースを形成します。

クラスローダーの種類:

  1. Bootstrap ClassLoader — JDKの基本クラスを読み込みます(rt.jarなど)。
  2. Extension ClassLoader$JAVA_HOME/lib/extから拡張を読み込みます。
  3. System (Application) ClassLoader — アプリケーションのclasspathからクラスを読み込みます。
  4. Custom ClassLoader — 動的読み込みのためのユーザー定義のローダー。

特徴:

  • クラスは(クラスローダー、クラス名)の組み合わせの範囲内でユニークと見なされます。
  • 異なるローダーによって読み込まれた同じクラスは異なるものと見なされます。
  • クラスローダーは階層を形成します(親-子)。
  • バイトからクラスを読み込むことが可能です(defineClass) — プラグイン/JSPなどにとって重要です。

微妙な質問。

同じクラスの異なるバージョンを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)を読み込むことができない場合の障害として現れました。