クラスローダ
Javaプログラムの実行を初めて目。
この図から、一般的に、Javaプログラムの動作を理解しやすいです。まず、あなたは、あなたのハードディスクに保存し、Javaコードを記述します。次に、コマンドラインに入力します。
javac YourClassName.java
この時点では、Javaコードをバイトコード(.classファイル)にコンパイルされています。あなたは、Eclipse IDEや他の開発ツールである場合は、コードを保存し、開発ツールは、そう、あなたが上記のコンパイル作業を完了手助けしなければなりませんあなたは、対応するディレクトリにクラスファイルを見ることができます。この時点で、クラスファイルがまだハードディスクに保存されているので、あなたは、コマンドラインを実行するとされます
java YourClassName
仕事に上記の赤いボックスを完了します。ローダへのJREがJVMに割り当てられたシステムメモリ領域にロードされ、ハードディスクからクラスファイルを読み込む - 実行データ領域(ランタイム・データの分野)実行エンジン次いで解釈またはコンパイルされたクラスファイル、特定のマシンコードにCPUが変換しましたしたがって全体のプロセスを完了し、CPUのマシンコードの実行、。
その後、我々はクラスローダは、正確な理由だったかに焦点を当てますか?仕事はどうですか?
まず、ローダー、少し抽象的、常に便利に機能のいくつかを見てみましょう。
「」階層
クラスローダは、父と息子の関係である関係の階層に編成されています。これは、ブートストラップクラスローダは、すべての父です。下図のように:
--bootstrapクラスローダ:
Java仮想マシンを実行する場合は、クラスローダが作成され、それはObjectクラスを含むいくつかの基本的なJava API、ロードされます。なお、クラスローダは、C / C ++の書き込みにJavaで書かれていますが、とされていません。
--extensionクラスローダ:
このローダは、クラスの安全性能に関連するいくつかを含め、基本的なAPIを超えて展開するクラスの数をロードします。(現在の理解は非常に深い、唯一の一般的な用語で、後日詳しく説明すると言うことができませんでした)
--systemクラスローダ:
それはあなたのクラスパスのクラスで構成されたアプリケーションクラスをロードします。
--user定義クラスローダー:
これは、開発者定義のカスタムClassLoaderクラスローダを拡大することである、いくつかのプログラマが定義したクラスをロードします。
「」委任モード(委任モード)
上記の階層構造を詳しく見て、JVMがクラスをロードするとき、下ローダーは、あなたが持っている場合、それは、クラスのロードされた名前空間となっているかどうかを確認するために、床の負荷、1クラスローダにタスクを委託されますロードされた、このクラスを直接使用しています。ロードされていない場合は、手数料の頂上まで続けます。検査が終わった後、ブートストラップローダは、このクラス、あなたはクラスファイルを見つけるまでダウン手数料を見つけることができない場合は、負荷に逆の順序で行いました。特定のクラスローダの場合は、1つのJavaクラスは、Java仮想マシンで言っていること、一度にロードすることができ、クラスは完全なID(クラスローダ、パッケージ、クラス名)です。レイは、異なるクラスローダをロードすることができます。
説明するために、具体的な例を与える、私は今のMyClassをロードする必要があるクラスの独自の定義を持って参加し、指定されていない場合は、一般的なクロスアプリケーション(システム)がロードされました。ミッションを受けた後、自分のライブラリーは、この種を持っているかどうか、システムチェックは、遅くとも拡張に委託見つかった、拡張が同じ検査を実行しない手数料をアップし続けていなかったことが判明、一番上のブーツカレーは、自分自身を見つけることができませんでしたので、そのパス(などのjava.langなどのJavaコア・クラス・ライブラリ)に応じてロードしようと、彼がしなければならなかったので、このMaClassクラスを見つけられませんでしたデリゲートまで(あなたのような人、あなたの完全なを与える、あなたは何もできない、私は他の誰かにそれを上に持っていました)拡張、拡張彼らのパスに(JAVA_HOME / JRE / libに/ EXT)を探している、または見つからない場合、ダウンし続け、その後、システムのローダーを探しているクラスパスパスには、発見した後、Java仮想マシンにロードされました。
今の調和、我々は同じ規則に従って、(拡張ローダーの負荷に相当)に行くと、最終的には拡張クラスMyClassのローダによってロードされ、参照するJAVA_HOME / JRE / libに/ extにこのパスは、このクラスを置くと仮定クラスは、JVMに二回ロードされているが、それぞれの時間は、異なるクラスローダによって行われます。
「」可視性の制限
下部ローダのみ言う下から上へ委任することはなく、その逆に、上部クラスローダに見ることができます。
「」アンカテゴリを許可しません
クラスローダは、クラスをロードすることができますが、それは、クラスをアンロードすることはできません。しかし、クラスローダは、削除または作成することができます。
ロードされたときに、クラスの後、JVMは以下の図に他の作業を続行します:
様々なステップの簡単のブロック図で次のように
ロード:クラスローディングの記事は先に説明し、JVM(運行データエリア)にロードされたクラスファイル・システム・メモリ
検証:ロードされたクラスファイルとJava仮想マシン仕様仕様かどうかをチェックします。
、必要な割り当てクラス用のメモリを必要とするデータ構造クラスの属性およびメソッドを決定する:準備。(クラスによって必要なメモリを割り当て、クラスに定義されたフィールド、メソッド、およびインタフェースを示すデータ構造を準備します。)
解決:クラスの定数プールのシンボリック参照を直接参照に変更されています。(かなり理解できません)
仮調印:静的初期化ブロックの実行中に、ローカル変数は、静的フィールドのクラスの割り当てを初期化します。
だから、クラスローダがクラスをロードし、それを仕事に何を行うことができますか?
詳細に運行データエリアを説明する必要がなければならないの詳細を理解しようとします。
第二に、運行データエリア
ランタイム・データエリア:JVMの例を実行している場合は、メモリ領域に割り当てられたシステムは、(このメモリ領域のサイズを設定できます)、メモリ領域は、JVM自身によって管理されています。等のような方法にパラメータを渡すために作成されたオブジェクトとして動作するデータの数、ローカル変数、戻り値を格納するために1つのメモリから分離 この作品アウトポイントは、運行データエリアと呼ばれています。Javaのスタック、プログラムカウンタレジスタ(PCレジスタ)、ネイティブメソッドスタック(ネイティブメソッドスタック)、Javaのヒープ領域のメソッド、定数プール操作(実行時定数プール):データ領域を操作する6つのチャンクに分割することができます。この方法を実行している定数プールは、地区に属している必要がありますが、そのために重要で、JVMの仕様では、独立して説明します。その中で、地域の3(PCレジスタ、Javaスタック、ネイティブメソッドスタック)の前に各スレッドが独立して所有され、後者の3つは、全体のJVMインスタンスの共通内のすべてのスレッドです。下に示すように6つのチャンク:
「PCカウンター:
各スレッドは、PCカウンタ、スレッドの開始は、(スタート)、PCカウンタが作成されると、カウンタが命令をバイトコード保存されている(JVM命令)が現在実行されているアドレスを持っています。
「Javaのスタック:
スレッドの起動時に各スレッドに同じ、Javaスタックを個別に作成、所有しています。スタックフレームは、直列スタック(スタック・フレーム)、JVMのみ圧入(プッシュ)とPOP(ポップ)、スタック・フレームの両方を格納しています。あなたがメソッドを呼び出すたびに、JVMは、メソッドの終了が戻ったときにスタックフレームをポップ、スタックフレームに圧入スタックに出て行きます。ときにメソッドの実行例外が発生した場合は、のprintStackTrace呼び出すことができる状況スタックを表示するために他の方法を。次のようにスタックの概略図
OK。今、各スタックフレームの詳細でみましょう外観は何かを置いています。この方法は、クラスの定数プール参照に属し、ローカル変数の配列、オペランドスタック:容易に明らか模式から、各スタックフレームは、3つの部分を含みます。
変数の「ローカル(現地)配列:
局所(ローカル)変数配列、メソッド、メソッドに渡されたパラメータは、ローカル変数に関連するオブジェクト参照を格納するために0から順。例えば:
public void doSomething(int a, double b, Object o) {
...
}
この方法の概要スタックフレームは、ローカル変数が格納されています。
0: this
1: a
2,3:b
4:0
ダブルBは、二つの連続インデックスを必要とするタイプ十分に確認してください。2の値は、インデックスから取り出された値。静的メソッドのために、この基準の記憶の配列は0ではなく、直接送信パラメータに格納されています。
「オペランドスタック:
オペランドスタックメソッドを実行するときにJVMプレス-POPまたは変数、中間変数を実行するためのいくつかの方法を格納します。実際に、この方法は、ローカル変数とオペランド定義に従ってスタック配列データ交換方法を実行するときに、オペランドスタックは、メソッドの実際の作業場所です。次のようにオペランドスタックであり、例えば、以下のコードは、実行されます。
int a = 90;
int b = 10;
int c = a + b;
この図では、点オペランドスタック100は、第一圧入ように、上側の上方に位置していることに留意されたいです。図から分かるように、オペランドスタックは、いくつかの中間変数を格納するために、実際にデータの一時記憶領域である、方法が終わって、何のオペランドスタック、それは存在しません。
「スタックフレームのデータ参照:
ローカル変数とオペランドスタックのアレイに加えて、スタックフレームは、また、定数プールを参照する必要があります。データはJVMの定数プールを実行するために必要な場合は、アクセスは定数プール参照を介してです。データスタックフレームにも責任アプローチと異常リターン。リターンによって復帰した場合、フレームは、プロセスのスタックJavaスタックからポップされます。メソッドに戻り値がある場合、戻り値はプロセスにオペランドスタックのメソッド呼び出しをプッシュされます。さらに、地域法に格納されたデータは、例外テーブル参照を促進することができます。以下の実施例は説明するために提示されています。
- クラス Example3C {
- パブリック静的ボイド addAndPrint(){
- 二重 結果= addTwoTypes(1 、88.88 )。
- System.out.println(結果)。
- }
- パブリック静的ダブル addTwoTypes(int型 I、 ダブル D){
- 戻る I + D;
- }
- }
class Example3C{
public static void addAndPrint(){
double result = addTwoTypes(1,88.88);
System.out.println(result);
}
public static double addTwoTypes(int i, double d){
return i+d;
}
}
コードが実行されると、Javaは次のようにスタック。
慎重マップを勉強する時間を取ります。スタックの底部上に、第一のスタックフレームaddAndPrint充電技術の方法は、その後、スタックフレームaddTwoTypes方法に押し込ま、留意されるべきです。エラーがあるマップ上の右端の文字が、結果はaddTwoTypesオペランドスタックaddAndPrint内に格納する必要があります。
「」ネイティブメソッドスタック
プログラムは、JNI(Javaのネイティブインタフェース)を介して(例えばCまたはC ++コードのような)ローカルメソッドを呼び出すと、ネイティブメソッドの対応するスタックの言語の種類に応じて確立しました。
「」メソッドのエリア
メソッド領域は、JVMインスタンスを起動するとき、メソッド領域が作成されたすべてのスレッドにより共有JVMインスタンスです。これは、バイトコードメソッド、スタティック変数、クラス、メソッドについて放電定数プール、フィールドおよび情報の操作を記憶するためのものです。実装時の異なるJVM実装面積が異なることになります。オラクルのHotSpotは永久に永久的なエリア(常駐領域)または置き換え(Permanent世代)と呼ばれます。
「」ファイル名を指定して実行定数プール
この領域と一定のストレージクラスインターフェースは、加えて、それはメソッドとフィールドへのすべての参照を保持しています。メソッドまたはフィールドが参照されている場合は、上のJVMは、定数プールを実行することにより、それらの参照のメモリ内の実際のアドレスメソッドやフィールドを検索します。
「」ヒープ(ヒープ)
ヒープは、作成したプログラムのオブジェクトまたはインスタンスに格納されます。このエリアJVMのパフォーマンスに大きな影響。これは、メモリのガベージコレクションプロセスのこの領域です。
そのため、クラスローダがロード実際にクラスコンパイルされたファイル、JVMのメモリバイトコードのJavaをロードし、初期化、実行のための実行エンジンで完全な運用データに基づいています。
第三に、実行エンジン(実行エンジン)
バイトコードのクラスローダがメモリにロードされた後に、Javaバイトコード命令の実行エンジンがうまくいけば、Javaバイトコードが読み込まれます。問題は、Javaバイトコードマシンが読まれていない今、それはまた、依存マシンコードのプラットフォームに変換バイトコードへの道を見つけなければならないということです。このプロセスは、あなたが完了するまでに時間コンパイラ(JITコンパイラ)を持つことができ、インタプリタにより実行することができます。