【java】JVMに入ると、浅い水でも魚を触ることができます

5801 ワード

これはjvmが何であるかを説明する文章ではなく、jvmのプラットフォーム間特性も紹介しないし、jvmのセキュリティ特性も説明する文章ではなく、jvm命令操作、データ演算を説明する文章ではなく、本文はタイプのライフサイクルに重点を置いている.
タイプのライフサイクルは、クラスのマウント、jvmアーキテクチャ、ゴミ回収メカニズムに関連します.
なぜjvmアーキテクチャについて話しますか?クラスのマウントとゴミ回収メカニズムはjvmアーキテクチャと密接に関係しているからです.
では、jvmアーキテクチャとは何でしょうか.
jvmが動作すると、システムにメモリ領域を申請します(異なるjvm実装は異なるかもしれませんが、仮想メモリを使用できるものもあります)、このメモリの一部を分けて多くのものを格納します.例えば、プログラムが作成したオブジェクト、メソッドに渡されるパラメータ、戻り値、ローカル変数などです.このメモリをランタイムデータ領域と呼び、ランタイムデータ領域をメソッド領域、スタック、javaスタック、pcレジスタ、ローカルメソッドスタック.上の図を見て、jvmシステムがどのようなものなのか、これらの説明を見て、jvmシステムがどのようなものなのかは大体理解できるかもしれませんが、実行時のデータ領域の中のメソッド領域などが何に使われているのかまだ分からないかもしれません.
メソッド領域:仮想マシンがclassファイルをロードすると、このclassファイルに含まれるバイナリデータからタイプ情報が解析され、メソッド領域に格納されます.メソッド領域はすべてのスレッドで共有されるため,データのスレッドセキュリティを考慮しなければならない.両方のスレッドがlavaのクラスを探している場合、lavaクラスがまだロードされていない場合は、1つのスレッドだけがロードされ、別のスレッドが待機する必要があります.
PCレジスタ:各新しいスレッド生成は、独自のpcレジスタとjavaスタックフレームを得る.
≪ヒープ|Heap|emdw≫:プログラムの実行時に生成されたすべてのオブジェクトを格納します.スタックはスレッド共有のメモリ領域なので、マルチスレッドプログラムを書くときに同時性を考慮する必要があります.
Javaスタック:javaスタックは、図のように多くのスタックフレームから構成され、スレッドがjavaメソッドを呼び出すと、仮想マシンは新しいスタックフレームをjavaスタックに押し込み、メソッドが戻るとjavaスタックからポップアップされ、捨てられる.
では、jvmがどのように働いているのか想像できるはずですが、具体的な仕事の原理を話すべきではないでしょうか.のしかし、急いでいないで、まずクラスのマウントメカニズムを理解します.
クラスのマウントメカニズムを理解する前に、jvm内のクラスマウント:BootstrapLoader、ExtClassLoader、AppClassLoader;ExtClassLoader(jreの下にあるrt.jar,charsets.jarのマウントを担当)とAppClassLoader(classpathの下にあるクラスパッケージの転載を担当)はClassLoader(抽象クラス)のサブクラスである.
BootstrapLoader(jreコアクラスライブラリのマウントを担当)はルートマウントで、c/c++で書かれていてjavaには見えません.
この3つのクラス・ローダには親子関係があり、ルート・ローダはExtClassLoaderの親ローダであり、ExtClassLoaderはAppClassLoaderの親ローダである.
Jvmにおけるクラスの搭載も安全機構砂箱モデルの最初の敷居である.Javaマウントクラスは、親委任モード、すなわち、委任メカニズムをすべて担当します.では、マウントの概要を説明します.
クラスをマウントする場合、ユーザーがクラスマウントを指定すると、そのクラスマウントは親マウントに委任され、ルートマウントに委任されます.javaがマウントされている場合、そのクラスマウントは親マウントに委任されます.lang.Stringは、コアクラスライブラリでマウントされているため、classオブジェクトを直接返します.ルートマウントで見つからないクラスであれば?次にサブクラス(次の親)マウントに渡され、クラスファイルが見つからない場合は、以前のユーザーが指定したクラスマウントによってマウントされます.(スーパークラスをマウントする手順は説明されていませんが、油断しないでください).
誰かが悪意を持って基礎クラスjavaを書いた場合.lang.String、それでは仮想マシンに影響しますか?このクラスは最終的にルート・ローダにロードされるためではなく、ルート・ローダはjreコア・クラス・ライブラリにロードされるだけで、最終的に返されるclassタイプはユーザーが書いたStringではなく、システムが持っているString、つまりユーザーが書いたStringは永遠にロードされません.
クラス・マウンタがどのように動作しているかを理解した後、classファイルのフォーマットも理解する必要があります.
 
TheClassFileStructure
ClassFile{
u4magic;//  
u2minor_version;//class    
u2major_version;//class    
u2constant_pool_count;//     
cp_infoconstant_pool[constant_pool_count-1];//   
u2access_flags;//   
u2this_class;//     
u2interfaces_count;
u2interfaces[interfaces_count];
u2fields_count;
field_infofields[fields_count];
u2methods_count;
method_infomethods[methods_count];
u2attributes_count;
attribute_infoattributes[attrributes_count];
}

 
私たちが理解しなければならないことはたくさんありますが、理解しにくいのはcpです.infoconstant_pool定数プール.
1つの定数プールには多くのテーブルがあります.
CONSTANT_Utf 8 UTF-8符号化Unicode文字列
CONSTANT_Integer intタイプのフォント値
CONSTANT_Float floatタイプのフォント値
CONSTANT_Long longタイプのフォント値
CONSTANT_Double doubleタイプのフォント値
CONSTANT_クラスまたはインタフェースのシンボル参照
CONSTANT_String Stringタイプのフォント値の参照
CONSTANT_フィールドへのField refのシンボル参照
CONSTANT_Method refクラス内のメソッドのシンボル参照
CONSTANT_InterfaceMethod ref 1つのインタフェース内のメソッドのシンボル参照
CONSTANT_NameAndTypeは、フィールドまたはメソッドの一部のシンボルを参照します.
これらの表の構造は私も説明しません.classファイルをよく知らなくても大丈夫です.大体知っていてもいいです.では、jvmシステム、クラスローダワークフローを理解しました.では、クラスローダワーク、jvm実行時のデータ領域の変化、メソッド領域の構造などを詳しく見てみましょう.
クラスマウントの過程で、各クラスマウントはメソッド領域にテーブルを形成し、このテーブルにはそのマウントと対応するクラスの権限の命名が記載されています.このような表がなくてjvm内部のネーミングスペースを形成しました.同時にメソッドエリアには,このクラスの定数プールなどの情報も含まれている.
では、これらといえば、実はこのプロセスはまだあいまいで、多くの知識も落ちています.では、詳細なマウントプロセスを見てみましょう.
通常のクラスをマウントする場合、クラスマウントのloadClassメソッドが呼び出され、マウントするクラスがネーミングスペースにマウントされていない場合、jvmはクラスマウント、すなわち定数プールCONSTANT_にそのタイプのフルリミット名を渡すClass_info親クラス、クラス・マウンタなどの情報が格納されている表)エントリのマウンタは、参照されるタイプをマウントしようとします.参照を開始するタイプがjvmマウンタによって定義されている場合は、jvmクラス・マウンタによってマウントされます.そうでない場合は、ユーザーがローダをカスタマイズします.参照されるタイプがマウントされると、jvmはそのバイナリ・データをよくチェックします.クラスがクラスである場合は、javaではありません.lang.Object.jvmは、データに基づいてその全制限定名を取得してマウントする(再帰的に適用された)このプロセスには、再帰的なスーパーインタフェースも必要である.
マウントの差は多くありません.完全なプロセスは、マウント接続--初期化です.
では、接続と初期化は一過性で、ゴミ回収に重点を置きます.
接続のプロセスは、主に検証(タイプがjava言語の意味に合致し、仮想マシンの完全性を危険にさらすことはないことを確認)、準備(java仮想マシンがクラス変数にメモリを割り当て、デフォルトの初期値を設計する)、解析(タイプの定数プールでクラス、インタフェース、ワードセグメント、メソッドの適合参照を探し、これらのシンボル参照を直接参照に置き換えるプロセス)です.
初期化の際,クラスに直接スーパークラスが存在し,スーパークラスがまだ初期化されていない場合は,まず直接スーパークラスを初期化する.初期化インタフェースは、親インタフェースを初期化する必要はありません.
補足:
Jvmあるメソッドを実行するとき、まずこのメソッドをjavaスタックに押し込み、ローカル変数などの情報が含まれていますが、オブジェクトはどこに入れますか?スタックに押し込まれるのは、オブジェクトの参照、すなわち変数であり、すべてのオブジェクトがスタックに格納されます.
なぜオブジェクトをスタックに入れ、変数などのデータをスタックに入れるのですか?はっきり言って、オブジェクトが大きすぎて、スタックに入れるのが面倒です.(もちろん標準的な回答はそうではありませんが、ここでは実質を説明するだけです)
このような過程を理解した後、私たちは必ずごみの回収メカニズムを理解しなければなりません.
きほんかいしゅうアルゴリズム
1.引用カウント:比較的古い回収アルゴリズム.このオブジェクトには参照があります.つまり、カウントを増やし、参照を削除するとカウントを減らします.ゴミ回収の場合、収集カウントが0の対象のみとなります.このアルゴリズムが最も致命的なのは、ループ参照を処理できない問題です.
2.タグ-消去:このアルゴリズムは2段階に分けて実行されます.第1のフェーズは、参照ルートノードからすべての参照オブジェクトをマークし、第2のフェーズはスタック全体を巡り、マークされていないオブジェクトをクリアします.このアルゴリズムでは、アプリケーション全体を一時停止するとともに、メモリの破片が発生します.
3.コピー:このアルゴリズムはメモリ領域を2つの等しい領域に分割し、毎回1つの領域のみを使用します.ごみ回収時には,現在使用されている領域を巡り,使用中のオブジェクトを別の領域にコピーする.セカンダリアルゴリズムは、使用中のオブジェクトのみを処理するため、レプリケーションコストが小さく、過去のレプリケーション以降も対応するメモリの整理が可能になりますが、フラグメントの問題が発生します.もちろん、このアルゴリズムの欠点も明らかですが、メモリ容量の2倍が必要です.
4.タグ-整理:このアルゴリズムはタグ-消去と複製の2つのアルゴリズムの利点を結合している.また、2段階に分けて、第1段階はルートノードからすべての参照オブジェクトをマークし、第2段階はスタック全体を遍歴し、未マークオブジェクトを消去し、生存オブジェクトをスタックの1つに圧縮し、順番に排出する.このアルゴリズムは、タグ-消去のフラグメント問題を回避し、レプリケーションアルゴリズムの空間問題も回避します.
5.増分収集:ゴミ回収アルゴリズムを実施する.即ち、応用しながらゴミ回収を行う.
6.世代別:対象ライフサイクルを分析したゴミ回収アルゴリズムに基づく.対象を若い世代、年老いた世代、持久世代に分け、ライフサイクルの異なる対象に対して異なるアルゴリズム(上記のいずれか)を用いて回収する.現在のゴミ回収器(J 2 SE 1.2から)はいずれもこのアルゴリズムを用いている.