2017-09-20 2 views
1

このテストケースでは、特定のクラスローダーインスタンスによってクラスAをロードしています。ただし、A.class.getClassLoader()はそのクラスローダーを取得しません。A.class.getClassLoader()がloader.loadClass( "A")によって使用されるローダーを返さない理由

class A{ 
    static { 
    ClassLoader loader = A.class.getClassLoader(); 
    System.out.println("A.<cinit>: " + loader); 
    } 
} 

class ClassLoaderGw extends ClassLoader { } 

public class App { 
    public static void main(String [] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { 
    ClassLoaderGw loader = new ClassLoaderGw(); 
    System.out.println("Main: " + loader); 
    Class<?> klass = loader.loadClass("A"); 
    Object obj = klass.newInstance(); 
    } 
} 

そして、これはクラスAppを実行しているの出力である:これはテストケースである

Main: [email protected] 
A.<cinit>: [email protected] 

私はクラスAの静的コンストラクタ内GwClassLoaderのインスタンスを取得できますか?

答えて

2

ClassLoaderGwは、いずれの方法もオーバーライドしないでClassLoaderに拡張されます。したがって、標準のloadClassメソッド(javadoc)の戦略に従います。これは親クラスローダに最初に委譲することです。

この場合、Aクラスは親クラスローダーのクラスパス上にありますので、そのがロードされます。

パズルの最後の部分は、getClassLoader()が、という実際にはがロードされたクラスローダーを返すことです。ロードを要求したクラスローダーではありません。私は、クラスAの静的コンストラクタ内GwClassLoaderのインスタンスを取得できますか


GwClassloaderは、クラスAの読み込みを担当していない限り、基本的には実行できません。

にすることができますか?まあ...別のクラスローディング戦略を使用していれば可能です。多分。 GwClassloaderAのバイトコードを見つけて、defineClassを呼び出すと、Aのクラスローダーになります。

しかし、クラスAが親クラスローダーによって読み込まれる可能性について心配する必要があります。そのようなことが起きた場合、同時に2つの異なるタイプの2つのタイプが存在する可能性があります。予期しない場所でクラスキャストの例外が発生する可能性があります。

+0

解決済み。 'defineClass'を呼び出すことで、意図したクラスの' classloader'になります。ここでは、['ClassLoaderGw'の新しい実装です(https://gist.github.com/fmcarvalho/1fecd5310f74c1153154886202a1e133#file-classloadergw-java) –

1

これはthe Javadocで説明されています

は、指定されたバイナリ名を持つクラスをロードします。このメソッドのデフォルトの実装では、次の順序でクラスを検索します。

  • クラスが既にロードされているかどうかを確認するには、findLoadedClass(String)を呼び出します。
  • 親クラスローダーでloadClassメソッドを呼び出します。親がnullの場合、代わりに仮想マシンに組み込まれたクラスローダが使用されます。
  • findClass(String)メソッドを呼び出してクラスを検索します。

(明示的なコンストラクタが存在しないため、暗黙的に、ClassLoaderGwクラスで呼び出される)default constructorのJavadocの中で説明したようので、あなたのClassLoaderは、親としてsun.misc.Launcher$AppClassLoader1があります

getSystemClassLoader()メソッドによって返されたClassLoaderを親クラスローダとして使用して、新しいクラスローダを作成します。

関連する問題