序文
Javaプロジェクトが開始されると、JVMがメインメソッドを見つけ、オブジェクト間の呼び出しに従って参照されたJARパッケージにクラスファイルとクラスファイルをロードすることを誰もが知っておく必要があります(ステップは、ロード、検証、準備、解析、使用、荷重に分割されます)。メソッド領域は、メモリを開き、クラスのランタイムデータ構造(静的変数、静的メソッド、定数プール、クラス構造などを含む)を保存し、同時に、対応するクラスオブジェクトが生成され、メソッド領域の対応するクラスランタイムデータ構造を指します。
最も単純な文で要約すると、クラスロードのプロセスは、JVMが必要なクラスファイルのパスに基づいてIOストリームを介してクラスバイトコードファイルを読み取り、一連の解析と初期化ステップを介してメモリに注入することです。 Javaのクラスローダーには、BootstrapClassloader(上層)、ExtClassLoader、AppClassLoader、およびユーザー定義のクラスローダー(下層)が含まれます。さまざまな種類のJARパッケージ(またはクラスファイル)の場合、JVMにはさまざまな種類のクラスローダーがあります。
対応する関係は次のとおりです。
bootstrapclassloaderは、JVMランニングに必要なクラスをロードするために使用されます。
java_home/jre/lib/resources.jar:java_home/jre/lib/rt.jar:java_home/jre/jre/lib/sunrasign.jar:java_home/jre/lib/jsse.jar:java_home/jre/lib/jce.Java_he/jre/jre/jre/jre java_home/jre/lib/jfr.jar:java_home/jre/lib/classes
extclassloaderは、拡張クラスのロードに使用されます。
../java/extensions:../java_home/jre/lib/ext:../library/java/extensions:/network/library/java/extensions:../system/library/java/extensions:../lib/java
AppClassLoaderは、プロジェクトのJARパッケージで参照されているClassPathおよびクラスの下で作成されたクラスをロードするために使用されます。
クラス全体のロードは、親代表団と呼ばれるメカニズムを介してロードされます。
たとえば、クラスは最低レベルのローダー(ユーザー定義のクラスローダー)によってロードされます。このローダーは、最初にロード用に前のレベルローダー(AppClassLoader)を呼び出し、AppClassLoaderは引き続きBootStrapClassloaderまでロードするために上位レベル(ExtClassLoader)に引き渡されます。 BootstrapClassloaderによってロードされたクラスパスがこのクラスを見つけることができない場合、ロード用の次のレイヤーのローダー(extClassoloader)に引き渡されます。このクラスが見つからない場合、ロードのために次のレイヤー(AppClassLoader)に引き継がれ続けます。など、ユーザー定義のクラスローダーがこのクラスを見つけることができない場合、プログラムはClassNotFounderrorをスローします。
負荷プロセス全体が次のように表示されます。
(画像はhttps://www.cnblogs.com/xing901022/p/4574961.htmlから引用されています)
クラスロードソースのソースコードトラッキングは次のとおりです(ソースコードはここで適切に簡素化されています)。読者はソースコードをクリックして表示できます。
パッケージjava.lang.classloader; import ......保護されたクラス<? ! ! class <?> c = findloadedclass(name); if(c == null){long t0 = system.nanotime(); try {if(parent!= null){//前のレイヤーローダーロードfirst c = parent.loadclass(name、false); } else {c = findbootstrapclassornull(name); }} catch(classNotFoundException e){// classNotFoundException classが見つかった場合はスローされます。 }} if(resolve){resolveclass(c); } return c; }}ソースコードの親委任メカニズムのプロセスを完全に理解できます。コードの最も重要な3つの文がマークされています。
ユーザーがカスタムローダーを必要とし、指定されたパスのクラスファイルをロードする場合、クラスローダーを継承し、FindClass(String名)メソッドを実装する必要があります。例として:
パッケージcom.linuxidc.utils; Import java.io.bytearrayoutputStream; Import java.io.fileinputStream; Import java.io.ioexception; Import java.io.inputStream; public class serviclassloader extends classloader {private string classpath; public serviceclassloader(string classpath){this.classpath = classpath; } /***親クラスのFindClassメソッドを書き直します。親クラスのロードクラスは、この方法を呼び出します */ @Overrideプロテクションクラス<? byte [] classData = getClassData(name); if(classdata!= null){c = defineclass(name、classdata、0、classdata.length); } else {throw new ClassNotFoundException(); } return c; } // IOストリームを介してクラスファイルを読み取り、バイト配列プライベートバイト[] getClassData(String name){String Path = classPath + "/" + name.Replace( '。'、 '/') + ".class"; inputstream iStream = null; bytearrayoutputStream bytearrayoutputStream = new bytearrayoutputStream(); {iStream = new fileInputStream(path); byte [] buffer = new byte [1024]; int temp = 0; while((temp = istream.read(buffer))!= -1){bytearrayoutputStream.write(buffer、0、temp); } if(bytearrayoutputStream!= null){return bytearrayoutputStream.tobytearray(); }} catch(例外e){e.printstacktrace(); }最後に{try {if(istream!= null){istream.close(); }} catch(ioexception e){e.printstacktrace(); } try {if(bytearrayoutputStream!= null){bytearrayoutputStream.close(); }} catch(ioexception e){e.printstacktrace(); }} nullを返します。 }}クラスローダーを使用するためのコードは次のとおりです。
serviceclassloader serviceclassloaser = new ServiceClassLoader( "c:/myclass"); czlass <?
同じServiceClassLoaderオブジェクトを使用して同じクラスファイルを複数回ロードすると、各ロードの後のクラスオブジェクトは同じです!ただし、新しい異なるカスタムクラスローダーが同じクラスファイルをロードすると、毎回別のクラスオブジェクトが返されます。
注:ロードするクラスファイルは、ClassPathディレクトリおよびサブディレクトリに配置することはできません。そうしないと、AppClassLoaderによって最初にロードされます(これは、クラスのロードが親の委任メカニズムを採用し、AppClassLoaderがクラスパスの下ですべてのクラスファイルをロードできるためです)。毎回、同じAppClassLoaderがロードされるため、クラスのキャッシュの問題があります。
これにより、JVMクラスがロードされたときに反射を直接使用する問題が解決します。
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。