SectionsEdit
Javaクラスファイル構造には10の基本セクションがあります:
- Magic Number: 0xCAFEBABE
- Version of Class File Format: Classファイルのマイナーおよびメジャーバージョン
- Constant Pool: クラスファイル内の定数。 クラスの定数プール
- アクセスフラグ:例えば、クラスが抽象的か、静的か、など
- このクラスです。 現在のクラスの名前
- スーパークラス。 スーパークラスの名前
- インターフェース。 クラス内のすべてのインターフェイス
- フィールド。 クラス内の任意のフィールド
- メソッド。 クラス内のすべてのメソッド
- Attributes:
Magic NumberEdit
クラスファイルは、以下の4バイトのヘッダ(16進数)で識別されます。 CA FE BA BE
(下表の最初の4つの項目)。 このマジック ナンバーの歴史は、James Gosling 氏が Palo Alto のレストランに言及して説明したものです:
「我々はよく St Michael’s Alley という場所にランチに行った。 地元の伝説によると、深く暗い過去に、グレイトフル・デッドが大成功する前に、そこで演奏していたそうです。 かなりファンキーな場所で、まさにGrateful Dead Kinda Placeだった。 ジェリーが亡くなった時には、小さな仏像のような神社まで建っていたそうです。 僕らがよく行っていた頃は、その場所をカフェ・デッドと呼んでいました。 いつの間にか、これがHEXナンバーであることに気がつきました。 ファイルフォーマットのコードを書き直しているときに、2つのマジックナンバーが必要になったんです:1つは永続オブジェクトファイル用、もう1つはクラス用です。 オブジェクトファイルのフォーマットにはCAFEDEADを使い、「CAFE」の後に続く4文字の16進数の単語をgrepしているうちに、BABEに行き当たり、それを使うことにしました。 そのため、CAFEBABEはクラス・ファイル・フォーマットになり、CAFEDEADは永続オブジェクト・フォーマットとなりました。 しかし、永続オブジェクト機能はなくなり、それとともに CAFEDEAD の使用もなくなり、最終的には RMI に置き換えられました。
General layoutEdit
クラスファイルは可変サイズのアイテムを含み、ファイルオフセット(またはポインタ)を埋め込まないため、通常は最初のバイトから終わりに向かって順にパースされます。
- u1: 符号なし 8 ビット整数
- u2: ビッグエンディアンバイトオーダーの符号なし 16 ビット整数
- u4: ビッグエンディアンバイトオーダーの符号なし 32 ビット整数
- table: ある型の可変長アイテムの配列である。 テーブル内の項目数は直前のカウント数(カウントはu2)で識別されるが、テーブルのバイトサイズは各項目を調べることによってのみ決定できる。
これらの基本型のいくつかは、文脈に応じて(文字列や浮動小数点数などの)より上位の値として再解釈される。
バイトオフセット | サイズ | タイプまたは値 | 説明 | |
---|---|---|---|---|
0 | 4バイト | u1 = 0xCA hex |
magic number (CAFEBABE) クラスファイルフォーマットに準拠したファイルであることを示すために使用 | |
1 | u1 = 0xFE hex |
|||
2 | u1 = 0xBA hex |
|||
3 | u1 = 0xBE hex |
|||
4 | 2 bytes | u2 | minorバージョンNo. | |
5 | ||||
6 | 2 bytes | u2 | 使用中のクラスファイルフォーマットのメジャーバージョン番号。
Java SE 17 = 61 (0x3D hex), の脚注1を参照。 |
|
7 | ||||
8 | 2バイト | u2 | 定数プールカウント、次の定数プールテーブルにおけるエントリ数です。 | |
9 | ||||
10 | table | constant pool table, a array of variable-sized constant pool entries, containing literal numbers, string, and references to class or methods. インデックスは1から始まり、(定数プール数 – 1) 合計のエントリ数を含みます (注を参照)。 | ||
… | ||||
…. | ||||
10+cpsize | 2 bytes | u2 | access flags.NET。 ビットマスク | |
11+cpsize | ||||
12+cpsize | 2 bytes | u2 | このクラスを特定するものです。 定数プールの “クラス “タイプのエントリへのインデックス | |
13+cpsize | ||||
14+cpsize | 2 bytes | u2 | スーパークラスであると認識されます。 クラス “タイプのエントリへの定数プールへのインデックス | |
15+cpsize | ||||
16+cpsize | 2 bytes | u2 | インタフェース数です。 5763> | |
17+cpsize | ||||
18+cpsize | isize (variable) | table | インターフェーステーブルにおけるエントリ数です。 このクラスが実装するインターフェイスを記述する定数プールのインデックスの可変長配列 | |
… | ||||
… | ||||
… | ||||
18+cpsize+isize | 2 bytes | u2 | field count, 以下のフィールドテーブルのエントリ数 | |
19+cpsize+isize | ||||
20+cpsize+isize | fsize (variable) | table | field table, 可変長フィールド配列
各要素はhttps://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5 |
|
で定義されたfield_info構造体である。.. | ||||
… | ||||
… | ||||
20+cpsize+isize+fsize | 2 bytes | u2 | method count.を参照。 以下のメソッドテーブルのエントリ数 | |
21+cpsize+isize+fsize | ||||
22+cpsize+isize+fsize | msize (variable) | table | method table, メソッドの可変長配列
各要素はhttps://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6 |
|
で定義されたmethod_info構造体です。.. | ||||
… | ||||
… | ||||
22+cpsize+isize+fsize+msize | 2 bytes | u2 | attribute count.の略です。 以下の属性テーブルのエントリ数 | |
23+cpsize+isize+fsize+msize | ||||
24+cpsize+isize+fsize+msize | asize (variable) | table | attribute table.Of a attribute | attribute table, 可変長の属性配列
各要素は、https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7 |
で定義されたattribute_info構造体です。… | ||||
… | ||||
… |
C言語ライクなプログラミング言語での表現編集
Cでは構造体に複数の可変長の配列はサポートしていないので、以下のコードはコンパイルできずデモとしてのみ機能することになります。
struct Class_File_Format { u4 magic_number; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces; u2 fields_count; field_info fields; u2 methods_count; method_info methods; u2 attributes_count; attribute_info attributes;}
The constant poolEdit
The constant pool table is where the most of the literal constant values are stored. これには、あらゆる種類の数値、文字列、識別子名、クラスとメソッドへの参照、およびタイプ記述子のような値が含まれる。 定数プール テーブル内の特定の定数へのすべてのインデックスまたは参照は、16 ビット (u2 型) の数値で示され、インデックス値 1 はテーブル内の最初の定数を指します (インデックス値 0 は無効です)。 まず、テーブルのインデックスは0ではなく1から始まりますが、カウントは実際には最大インデックスに1を足したものと解釈されるべきです。 さらに、2 種類の定数 (longs と doubles) がテーブルの 2 つの連続したスロットを占めますが、2 番目のスロットは直接使用されることのないファントム・インデックスです。 このタグに続くバイト数とその解釈は、タグの値によって決まります。 有効な定数の型とそのタグの値は次のとおりである。
タグバイト | 追加バイト | 定数の説明 | 導入バージョン | |||
---|---|---|---|---|---|---|
1 | 2+xバイト (変数) |
UTF-8 (Unicode) 文字列.utf.utf.utf.utf.utf.utf.utf.utf.utf.utf.utf.を含む。 文字列の前に、直後に続く符号化文字列のバイト数(文字数とは異なる場合がある)を示す16ビットの数値(u2型)を付けたもの。 | 1.0.2 | |||
3 | 4 bytes | Integer: ビッグエンディアン形式の符号付き32ビット2補数 | 1.0.2 | |||
4 | Float: 32ビット単精度IEEE 754浮動小数点数 | 1.0.2 | ||||
5 | 8 bytes | Long: ビッグエンディアン形式の符号付き64ビット2の補数(定数プールテーブルの2スロットを使用) | 1.0.2 | |||
6 | 8 bytes | Double: 64ビット倍精度IEEE754浮動小数点数(定数プールテーブルで2スロット使用) | 1.0.2 | |||
7 | 2 bytes | Class reference: 完全修飾クラス名(内部フォーマット)を含む UTF-8 文字列への定数プール内のインデックス(ビッグエンディアン) | 1.0.2 | |||
8 | 2 bytes | String reference: UTF-8 string (big-endian too) | 1.0.1 | 1.0 | 2 bytes | String reference: 定数プールのインデックス。2 |
9 | 4 bytes | Field reference: 定数プール内の2つのインデックス、最初のインデックスはクラス参照、次のインデックスは名前およびタイプ記述子を指します。 (ビッグエンディアン) | 1.0.2 | |||
10 | 4 bytes | Method reference: constant pool 内の 2 つのインデックス、最初のインデックスは Class 参照、次のインデックスは Name and Type ディスクリプタへのポインタを指します。 (ビッグエンディアン) | 1.0.2 | |||
11 | 4 bytes | インターフェイス メソッド リファレンス:定数プール内の 2 つのインデックス、最初のインデックスはクラス リファレンス、次のインデックスは Name and Type ディスクリプタへのポインティングです。 (ビッグエンディアン) | 1.0.2 | |||
12 | 4 bytes | Name and type descriptor: 2 つのインデックスがあり、最初のものは名前 (identifier) 、2番目は特別にコード化したタイプ デスクリプタである定数プール内の UTF-8 文字を指します。 | 1.0.2 | |||
15 | 3 bytes | Method handle: この構造はメソッドハンドルを表すために使われ、1バイトのタイプディスクリプタと、定数プール内のインデックスから構成されています。 | 7 | |||
16 | 2 bytes | Method type: この構造体はメソッドタイプを表すために使用され、定数プール内のインデックスで構成される。 | 7 | |||
17 | 4 bytes | Dynamic: ブートストラップメソッドの呼び出しによって動的に生成された定数を指定するために使用される。 | 11 | |||
18 | 4 bytes | InvokeDynamic: invokedynamic 命令が使用し、起動メソッド、動的呼び出し名、呼び出しの引数と戻り値の型、オプションとして起動メソッドの static 引数と呼ぶ追加定数の列が特定されます。 | 7 | |||
19 | 2 bytes | Module: モジュールを識別するために使用されます。 | 9 | |||
20 | 2 bytes | Package: モジュールによってエクスポートまたはオープンされたパッケージを識別するために使用されます。 | 9 |
整数型定数は integer と long の2種類のみです。
Javaのクラス名は、完全に修飾されている場合、伝統的に “java.lang.Object” のようにドットで区切られます。 しかし、低レベルのクラス参照定数内では、代わりに “java/lang/Object” のようにスラッシュを使用する内部形式が現れます。
Unicode 文字列は、「UTF-8 文字列」という名目にもかかわらず、類似しているものの、実際には Unicode 標準に従って符号化されていません。 2つの違いがあります(完全な議論についてはUTF-8を参照してください)。 第一は、コードポイントU+0000が、標準のシングルバイトのエンコーディング00
ではなく、2バイトのシーケンスC0 80
(16進数)としてエンコードされていることです。 第二の違いは、補足文字(U+10000以上のBMP外の文字)が、UTF-8で直接エンコードされるのではなく、UTF-16と同様のサロゲートペア構造でエンコードされる点です。 こ の場合、 2 個のサ ロ ゲー ト はそれぞれ UTF-8 で別々に符号化 さ れます。 た と えば U+1D11E は、 正 し い 4 バ イ ト の UTF-8 符号化である F0 9D 84 9E
.
ではなく、 6 バ イ ト 列ED A0 B4 ED B4 9E
と して符号化 さ れま し た。