クラスのロード
1.仮想マシン
完了するために、ブートストラップクラスローダクラスによって作成された初期の仮想マシンは、このクラスは、仮想マシンの特定の実装によって指定されます。そして、この最初のクラスのJava仮想マシンのリンクに、それを初期化し、メソッドを呼び出してpublic static void main(String[] args)
、彼らは全体のプロセスを開始した後、。他のクラス、インターフェイスやメソッドへのJava仮想マシンのリンクを引き起こす可能性があり、Java仮想マシン命令のmainメソッドを実行します。
2.ロード
- クラスの完全修飾名で定義されたバイナリバイトストリームを取得するには、
- これは、実行時のデータ構造に静的記憶構造のバイトストリームを表します。
- メモリ内に生成することは、様々なデータエントリのアクセスクラスとして、このクラスのjava.lang.Classオブジェクトを表します。
ロード・フェーズと接続フェーズのプロセスの一部は、ステージが完了していないクロスロードは、接続フェーズが開始されている可能性が行われるが、それらは、接続フェーズ、開始時刻の内容に属し、まだ、操作のロード・フェーズ中に摘発されたこれら二つの段階これは、固定された順序を維持しました。
3.確認してください
最初のステップは、目的は、クラスに含まれる情報のバイトストリームファイルが自分自身の安全を危うくしません、現在の仮想マシンと仮想マシンの要件を満たしていることを確認することで、接続フェーズを確認することです。
非本質的な検証フェーズ、それが参照されるクラスは、後に検証を繰り返した場合、時間に仮想マシンのクラスのロードを短縮するために、クラスの検証措置のほとんどをシャットダウンする-Xverifynoneパラメータを使用することを検討して、プログラムの実行には影響を与えません。
4.準備
準備フェーズは、正式にクラス変数にメモリを割り当て、ステージクラス変数の初期値が設定されています。オブジェクトはヒープにインスタンス化されるとき、この時間は、インスタンス変数を含まない、(静的変数が変更された)専用メモリ割り当てクラス変数を含む、インスタンス変数は、オブジェクトと一緒に割り当てられます。「通常」は、本明細書中でゼロ値のデータ型の初期値であると称される。
例えば、クラス変数の定義は考える:public static int value=123;
その準備フェーズ0の代わりに、123後の初期値を持つ変数の値。この時間はまだJavaメソッドを開始し、123に割り当てられた値いないためputstatic
、プログラムがコンパイルされた後、命令、クラスのコンストラクタメソッドに寄託されなければならないので、123のアクションに割り当てられた値は、初期化フェーズで実行されます。
「特殊なケース」のための手段として:public static final int value=123
クラス属性フィールドが一定値である場合、すなわち、製剤は、準備段階123で値の最終的な値ではなく0に初期化されるように、それがマークされ、初期化段階で指定された値となります。
5.解析
ステージを解析すると、直接参照を交換するプロセスへのシンボリック参照の定数プールへの仮想マシンです。
6.初期化
初期化フェーズは、クラスをロードするプロセスの最終段階で、この時間は本当にクラスで定義されたJavaコードを実行し始めました。準備段階では、変数は、プログラムや他のリソースを開発した主観スケジューラ猿に基づいて、クラス変数を初期化するために、システム要件に一度、および初期化フェーズでの初期値の上に割り当てられた、またはされています:初期化フェーズは、実装クラスのコンストラクタである<clinit>()
方法プロセス。
<clinit>()
この方法は、すべてのクラス変数や文の静的ブロック、コンパイラ自動的に収集クラスの代入演算であるstatic{}
文の合併順次コンパイラコレクションは、意思決定のソースファイルに文で出現順にのみ静的文ブロックでした前の文のブロック内で定義された静的変数へのアクセスは、その背後にある変数の定義は、ブロックの前で静的ステートメントを割り当てることができますが、アクセスすることはできません。
クラスローダ
クラスローディング相は、達成するために必要なクラスを取得する方法を決定するためのアプリケーションを許可するために達成するために、外部のJava仮想マシンにこのアクション、「バイナリバイトストリームのクラス記述の完全修飾名を介して取得します」このアクションコード・モジュールは、「クラスローダ」と呼ば
1.親委譲モデル
クラスローダクラスローダを要求されたとき、それは最初にこのクラスをロードしようとするために所有していませんが、この要求は完了するために、親クラスローダに委譲されているので、すべてのクラスが、最終的にトップを開始するためにロード要求を提供すべきですクラスローダは、親クラスローダは、彼らが要求を完了することはできませんフィードバックをロードするときにのみ、子ローダは、独自のをロードしようとします。
両親は委任モデルの利益:クラスローダと一緒にJavaクラスの優先順位の階層関係を。クラスローダ環境の様々なクラスを確認し、彼らは同じクラスです。
- クラスローダを起動します。\ libディレクトリを読み込みます
- 拡張クラスローダ:負荷の\ lib \ extディレクトリ
- アプリケーションクラスローダ:デフォルトのクラスローダ
- カスタムクラスローダ
2.破壊両親委譲モデル
両親のデリゲートモデルを破壊するには?
ClassLoaderクラスの継承、のloadClass findClassメソッドとメソッド、次のサンプルコードをオーバーライドします。
public class TestClassLoader extends ClassLoader {
private String name;
public TestClassLoader(ClassLoader parent, String name) {
super(parent);
this.name = name;
}
@Override
public String toString() {
return this.name;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
ClassLoader system = getSystemClassLoader();
Class<?> clazz = system.loadClass(name);
if (clazz != null)
return clazz;
return findClass(name);
}
@Override
public Class<?> findClass(String name) {
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
is = new FileInputStream(new File("d:/Test.class"));
int c;
while (-1 != (c = is.read())) {
baos.write(c);
}
data = baos.toByteArray();
} catch (Exception e) {
//...
} finally {
try {
is.close();
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return this.defineClass(name, data, 0, data.length);
}
public static void main(String[] args) throws Exception {
TestClassLoader loader = new TestClassLoader(TestClassLoader.class.getClassLoader(), "TestLoaderN");
Class clazz = loader.loadClass("test.classloader.Test");
clazz.newInstance();
}
}
public class Test {
public Test(){
System.out.println(this.getClass().getClassLoader().toString());
}
}