、sun.misc.Launcher(ExtClassLoaderとAppClassLoaderを作成します)
パブリックランチャー(){ Launcher.ExtClassLoader VAR1。 試す{ VAR1 = Launcher.ExtClassLoader.getExtClassLoader()。 } キャッチ(のIOException var10){ スロー 新しい InternalErrorを( "拡張クラスローダーを作成できませんでした" 、var10)。 } 試みる{ この .loader = Launcher.AppClassLoader.getAppClassLoader(VAR1)を、 } キャッチ(IOExceptionをvar9){ スロー 新しい( "アプリケーションクラスローダを作成できませんでした" InternalErrorを、var9を)。 } Thread.currentThread()setContextClassLoader(。この.loader)。 ストリングVAR2 =はSystem.getProperty( "java.security.manager" )。 もし(!var2の= ヌル){ SecurityManagerのVAR3 = nullを。 もし(! ""。!)VAR2(等しい&& "デフォルト" .equals(var2の)){ しようと{ VAR3 =(のSecurityManagerを)この).newInstance(.loader.loadClass(VAR2)を、 } キャッチ(IllegalAccessExceptionがVAR5){ } キャッチ(ないInstantiationException var6){ }キャッチ(ClassNotFoundExceptionがvar7){ } キャッチ(にClassCastExceptionがvar8){ } } 他{ VAR3 = 新しいセキュリティマネージャ()。 } 場合(VAR3 == nullが){ スロー 新しい InternalErrorを( "セキュリティマネージャを作成できませんでした:" + var2に)。 } System.setSecurityManager(VAR3)。 } }
第二に、カスタムクラスローダ(ClassLoaderクラスの継承は、上書きにfindClassメソッド任命メカニズムを破壊するloadClassメソッドを書き換えることは推奨されません)
試験荷重クラス、の.classファイルに.javaファイルをコンパイルするjavacのを使用
パッケージコム; パブリック クラスこんにちは{ 静的{ System.out.printlnは( "こんにちは!" ); } 公共 のボイドsayHi(文字列名){ System.out.printlnは( "こんにちは!" + 名)。 } }
クラスローダは、パッケージ名にクラスパス名をロードするように注意を払います
パッケージコム; 輸入java.io.ByteArrayOutputStreamを。 インポートのjava.io.File; 輸入java.io.FileInputStream; 輸入java.io.InputStreamを。 輸入java.lang.reflect.Methodオブジェクト。 パブリック クラス ClassLoaderTestが延びClassLoaderを{ 民間 最終 静的 filePathSuffix =「の.class」ストリング。 プライベート文字列filePathPrefix。 公共ClassLoaderTest(文字列filePathPrefix){ この .filePathPrefix = filePathPrefix。 } @Override 保護クラスにfindClass(文字列名)<?> { 文字列fileNameに = name.split( "\\。")[name.split( "\\。")長さ- 1 ]。 バイト []バイト= loadClassDataメソッド(filePathPrefix + fileNameに+ filePathSuffix)。 戻り defineClass(名前、バイト、0 、bytes.length)を、 } プライベート バイト[] loadClassDataメソッド(文字列filePathに){ に入力ストリーム = NULL ; ByteArrayOutputStreamアウト = nullを。 試す{ に = 新しい(FileInputStreamを新しいファイル(filePathに)); アウト= 新しいByteArrayOutputStream(); int型私= 0 ; 一方、(!(I = in.read())= -1 ){ out.write(I)。 } } キャッチ(例外e){ e.printStackTrace(); } 最後に{ 試みる{ out.closeを(); in.close(); } キャッチ(例外e){ e.printStackTrace(); } } リターン)(out.toByteArray。 } 公共の 静的な 無効メイン(文字列[]引数)をスロー例外{ ClassLoaderTest CLT = 新しい ClassLoaderTest( "Dを:/" )。 クラスc = clt.loadClass( "com.Hello" )。 System.out.println(c.getClassLoader())。 System.out.println(c.getClassLoader()のgetParent()。)。 System.out.println(c.getClassLoader()のgetParent()のgetParent()); System.out.println(c.getClassLoader()のgetParent()のgetParent()のgetParent()。。。)。 方法sayHi = c.getMethod( "sayHi"、文字列。クラス)。 // 无参实例化 オブジェクトO = c.newInstance()。 // 调用方法 sayHi.invoke(O、 "zhangsan" ); } }
三、ClassLoader.loadClass和にClass.forName()()
forName0を呼び出し、2番目の引数がtrueの場合、デフォルトの初期化は、偽の使用としてのオーバーロードされたメソッドを指定することができます
@CallerSensitive パブリック 静的 <?>クラスにforName(文字クラス名)をスローにClassNotFoundException { クラスの <?>発信者= Reflection.getCallerClass()。 返す forName0(classNameの、真の、ClassLoader.getClassLoader(呼び出し元)、呼び出し側); }
オーバーロードされたメソッドはloadClassを呼び出し、デフォルトがリンクされていない、それが初期化されません。
公共 <?>クラスのloadClass(文字列名)がスローClassNotFoundExceptionが{ 返すのloadClassを(名前、偽); }
上記の例でのHelloクラス、Hello1という名前の新しいCOMパッケージで同じファイル
パブリック 静的 ボイドメイン(文字列[]引数)がスロー例外{ // 加载、链接、初始化 にClass.forName( "com.Hello1" )。 System.out.println( "==========================================" ); // 加载、链接 にClass.forName( "com.Hello1"、偽、ClassLoader.getSystemClassLoader()); System.out.println( "==========================================" ); // 加载 。ClassLoader.getSystemClassLoader()はloadClass( "com.Hello1" ); }
第四に、スレッドコンテキストクラスローダ(ThreadContextClassLoader)
https://mp.weixin.qq.com/s/4FJbRLUcg8FmOqP1uz3f2A
メソッドgetContextClassLoader()とスレッドのコンテキストクラスローダを取得し、設定するsetContextClassLoader(クラスローダCL)java.lang.Threadから。
setContextClassLoader(クラスローダCL)メソッドを介して設定されていない場合、スレッドは親スレッドのコンテキストクラスローダのを継承します。
Javaのアプリケーションコンテキストクラスローダを実行する初期スレッドは、システムクラスローダです。
スレッドスレッド= 新しいスレッド(() - > { しようと{ クラス <> AClassは=にThread.currentThread()getContextClassLoader()はloadClass( "com.Hello"?。。); System.out.printlnは(aClass.getClassLoader()) ; } キャッチ(ClassNotFoundExceptionが電子){ e.printStackTrace(); } })。 thread.setContextClassLoader(新 ClassLoaderTest( "D:/" )); thread.start(); Thread.sleep( 1000年); スレッド = 新しいスレッド(() - > { しようと{ クラス<?>。AClassは=にThread.currentThread()getContextClassLoader()はloadClass( "com.Hello1" )。 System.out.println(aClass.getClassLoader())。 } キャッチ(ClassNotFoundExceptionが電子){ e.printStackTrace(); } })。 thread.start();
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.3.2