ホームページ  >  記事  >  Java  >  Java仮想マシンのクラスファイル構造の紹介

Java仮想マシンのクラスファイル構造の紹介

零下一度
零下一度オリジナル
2017-06-25 10:41:041500ブラウズ

1. はじめに

Java を勉強している友人なら、Java は当初から「一度書けばどこでも実行できる」という旗印を掲げてきたことを知っているはずです。実際、独立性に関して言えば、Java プラットフォームには別の特徴があります。言語の独立性を実現するには、Java システムのファイル構造またはバイトコードが非常に重要です。1 つは Java 言語仕様です。もう 1 つは Java 仮想マシン仕様です。Java 言語仕様は Java 言語に関連する制約とルールのみを規定していますが、仮想マシン仕様は真にクロスプラットフォームの観点から設計されています

おそらくほとんどのプログラマーは、Java 仮想マシンが Java プログラムを実行するのは自然で自然なことだと考えていると思いますが、今日、商業組織やオープンソース組織は、Java 言語以外の Java 仮想マシンに基づいた製品を多数開発しています。 Clojure、Groovy、JRuby、Jython、Scale などの実行言語。 Java コンパイラを使用して、Java コードをバイトコードを格納する Class ファイルにコンパイルすることもできます。また、JRuby などの他の言語のコンパイラを使用して、プログラム コードを Class ファイルにコンパイルすることもできます。 Java 仮想マシンは、プラットフォームに依存しない同じバイトコードをロードして実行できるためです。言い換えれば、言語プラットフォームの独立性を実現するための基盤は、仮想マシンとバイトコードのストレージ形式です。仮想マシンは、クラス ファイルの構造に準拠している限り、クラスがどの言語からのものであるかを気にしません。 Java 仮想マシン。

2. クラスファイルのエンコーディングと構成

1) クラスファイルはバイト (8 ビット) ベースのバイトストリームで構成されており、これらのバイトストリームは規定の順序に従って配置されており、バイト間に隙間はありません。 8 バイトを超えるデータはビッグエンディアン順に格納されます。つまり、上位バイトは下位アドレスに格納され、下位バイトは上位アドレスに格納されます。 PowerPC アーキテクチャはビッグ エンディアンのストレージ順序を使用するのに対し、x86 シリーズ プロセッサはリトル エンディアンのストレージ順序を使用するため、クラス ファイルを各プロセッサに格納するには、統一されたストレージ シーケンスを維持する必要があります。ミッドプロセッサ アーキテクチャ、仮想マシンの仕様はそれを統一する必要があります。

2) クラス ファイル構造は、C 言語に似た構造を使用してデータを格納します。データ項目には主に 2 つのタイプがあり、符号なし数値は数値、インデックス参照、文字列などを表現するために使用されます。 u1、u2、u4、u8 はそれぞれ 1 バイト、2 バイト、4 バイト、8 バイトの符号なし数値 を表し、 テーブルは複数の符号なし数値と他のテーブル構造 の複合体です。おそらくここにいる皆さんは、上記の符号なしの数値やテーブルが何なのかよくわかっていないかもしれませんが、それは問題ではありません。以下の例を待っているときに、例を挙げて説明します。 上記 2 つの点を明確にした後、クラス ファイル内で厳密な順序で配置されたバイト ストリームに含まれる特定のデータを見てみましょう:

ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

上の図を見るとき、注意する必要があることが 1 つあります。たとえば、上の図では、cp_info は定数プールを表しており、定数プールに constant_pool_count- があることを示しています。ここでは配列形式で表していますが、すべての定数プールの定数の長さが同じであると誤解しないでください 実際、ここでは説明の便宜上、配列メソッドを使用しています。 int 型の配列が毎回同じ長さになるプログラミング言語とは異なります。

3. クラスファイル構造の各部分の詳細な紹介

1) u4 マジックはマジックナンバーを表し、マジックナンバーは 4 バイトを占めます。これは実際には、ファイル タイプが JPG 画像や AVI ムービーではなく、Class ファイルであることを意味します。 Class ファイルに対応するマジックナンバーは 0xCAFEBABE です。

2) u2minor_version は Class ファイルのマイナー バージョン番号を表し、このバージョン番号は u2 型の符号なし数値表現です。
3) u2 Major_version はクラス ファイルのメジャー バージョン番号を表し、メジャー バージョン番号は u2 型の符号なし数値表現です。
major_version とminor_version は主に、現在の仮想マシンがクラス ファイルの現在のバージョンを受け入れるかどうかを示すために使用されます。 Java コンパイラのバージョンによってコンパイルされるクラス ファイルのバージョンは異なります。 上位バージョンの仮想マシンは、下位バージョンのコンパイラによってコンパイルされたクラス ファイル構造をサポートします。たとえば、Java SE 6.0 に対応する仮想マシンは、Java SE 5.0 のコンパイラによってコンパイルされた Class ファイル構造をサポートしますが、その逆はサポートしません。 4) u2 constant_pool_count は定数プールの数を表します。ここで、定数プールが何であるかに注目する必要があります。Jvm メモリ モデルの実行時定数プールと混同しないでください。クラス ファイルの定数プールには、主に文字列とシンボル参照が含まれます。最終定数の値やプロパティの初期値など。シンボル参照には主にクラスとインターフェイスの完全修飾名、フィールドの名前と記述子、メソッドの名前と記述子が格納されます。ここでの名前は簡単です。皆さん、ディスクリプタの概念については、以下でフィールド テーブルとメソッド テーブルについて説明します。また、Jvmのメモリモデルはヒープ、スタック、メソッド領域、プログラムカウンターで構成されているのは皆さんご存知の通りで、メソッド領域にはランタイム定数プールと呼ばれる領域がありますランタイム定数プールに格納されているのは実際にあるものです。コンパイラによって生成されるさまざまなリテラルとシンボル参照ですが、実行時定数プールは動的です。最も代表的なものは、
Stringのインターンメソッドです。 5) cp_info は、上記のさまざまなリテラルとシンボル参照を含む定数プールを表します。定数プールに配置されるデータ項目には合計 14 個の定数があり、各定数はテーブルであり、各定数は定数のタイプを示す共通の部分タグを使用します。

定数型CONSTANT_Class7CONSTANT_Fieldref 10
CONSTANT_Class 7
CONSTANT_Fieldref 9
CONSTANT_Methodref 10
CONSTANT_InterfaceMethodref 11
CONSTANT_String 8
CONSTANT_Integer 3
CONSTANT_Float 4
CONSTANT_Long 5
CONSTANT_Double 6
CONSTANT_NameAndType 12
CONSTANT_Utf8 1
CONSTANT_MethodHandle 15
CONSTANT_MethodType 16
CONSTANT_InvokeDynamic9

CONSTANT_Methodref
🎜🎜CONSTANT_InterfaceMethodref🎜🎜11🎜🎜🎜 🎜CONSTANT_String🎜🎜8🎜🎜🎜🎜CONSTANT_Integer🎜🎜3🎜🎜🎜🎜CONSTANT_Float 🎜🎜4🎜🎜🎜🎜CONSTANT_Long🎜🎜5🎜🎜🎜🎜CONSTANT_Double🎜🎜6🎜🎜🎜 🎜CONSTANT_NameAndType🎜🎜12🎜🎜🎜🎜CONSTANT_Utf8🎜🎜1🎜🎜🎜🎜CONSTANT_MethodHandle 🎜🎜15🎜🎜🎜🎜CONSTANT_MethodType🎜🎜16🎜🎜🎜🎜CONSTANT_InvokeDynamic🎜🎜18🎜🎜🎜 🎜🎜🎜


6)u2 access_flags 表示类或者接口的访问信息,具体如下图所示:

Flag Name Value Interpretation
ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its package.
ACC_FINAL 0x0010 Declared final; no subclasses allowed.
ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the invokespecial instruction.
ACC_INTERFACE 0x0200 Is an interface, not a class.
ACC_ABSTRACT 0x0400 Declared abstract; must not be instantiated.
ACC_SYNTHETIC 0x1000 Declared synthetic; not present in the source code.
ACC_ANNOTATION 0x2000 Declared as an annotation type.
ACC_ENUM 0x4000 Declared as an enum type.

7)u2 this_class 表示类的常量池索引,指向常量池中CONSTANT_Class的常量
8)u2 super_class 表示超类的索引,指向常量池中CONSTANT_Class的常量
9)u2 interface_counts 表示接口的数量
10)u2 interface[interface_counts]表示接口表,它里面每一项都指向常量池中CONSTANT_Class常量
11)u2 fields_count 表示类的实例变量和类变量的数量
12) field_info fields[fields_count]表示字段表的信息,其中字段表的结构如下图所示:

field_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

上图中access_flags表示字段的访问表示,比如字段是public、private、protect 等,name_index表示字段名称,指向常量池中类型是CONSTANT_UTF8的常量,descriptor_index表示字段的描述符,它也指向常量池中类型为 CONSTANT_UTF8的常量,attributes_count表示字段表中的属性表的数量,而属性表是则是一种用与描述字段,方法以及 类的属性的可扩展的结构,不同版本的Java虚拟机所支持的属性表的数量是不同的。
13) u2 methods_count表示方法表的数量
14)method_info 表示方法表,方法表的具体结构如下图所示:

method_info {
    u2             access_flags;
    u2             name_index;,
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

其中access_flags表示方法的访问表示,name_index表示名称的索引,descriptor_index表示方法的描述符,attributes_count以及attribute_info类似字段表中的属性表,只不过字段表和方法表中属性表中的属性是不同的,比如方法表中就有Code属性,表示方法的代码,而字段表中就没有Code属性。
15) attribute_count表示属性表的数量,说到属性表,我们需要明确以下几点:
属性表存在于Class文件结构的最后,字段表,方法表以及Code属性中,也就是说属性表中也可以存在属性表,属性表的长度是不固定的,不同的属性,属性表的长度是不同的

以上がJava仮想マシンのクラスファイル構造の紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。