第四章クラスファイル形式
この章では、クラスファイル形式のJava仮想マシンを記述しています。各クラスファイルは、単一のクラスまたはインタフェースの定義が含まれています。ファイルで定義されていない必ずしもすべてのクラス及びインターフェース(例えばクラスとインタフェースとしては、直接クラスローダによって生成することができる)がクラスまたはインタフェースが、クラスファイル形式と呼ばれる口語、我々は、任意の有効を表します。クラスファイルは、8ビットのバイトストリームで構成されています。すべての16ビット、32ビットおよび64ビットの数は、それぞれ2つ、4つ、8つの連続した8ビットのバイトを読み取ることによって構成されています。ビッグエンディアンモードを使用して保存されたマルチバイトのデータ、すなわち、エンディアン。Java SEのプラットフォームでは、このフォーマットは、インタフェースjava.io.DataInput及びjava.io.DataOutputのとにjava.io.DataInputStreamおよび他のタイプ、例えばjava.io.DataOutputStreamのメソッドによってサポートされています。
クラスファイルデータを表す第一章データ型の独自のセット:タイプU1、U2、及びU4は、符号なしバイト、2バイト、4つのバイトを表します。Java SEのプラットフォームのこれらのタイプではreadUnsignedByte、readUnsignerShortのreadIntとメソッドのインタフェースによって読み取らjava.io.DataInput。
インターフェース本体と同様C章擬似言語の構造は、クラスファイル形式を表現します。クラスと混乱の概念を避けるために他のフィールドの例としては、クラスファイル形式の構造の説明は、アイテム(アイテム)となります。連続したアイテムを順次クラスファイルに格納され、位置合わせの間に充填されていません。
テーブルは、可変サイズの0個以上の項目で構成され、これは、複合構造体のシリーズを表すクラスファイルのために使用されます。我々はCに類似の配列構文を使用しているがエントリを参照するが、テーブルが直接バイトオフセットテーブルに変換できないファクトテーブルインデックス手段の異なるサイズの構造のストリームです。
我々は、データ構造の配列として表現するとき、アレイは固定サイズで構成されるゼロ以上の隣接する項目で構成され、それが配列のインデックスを作成してアクセスすることができます。
この章では、ASCII文字参照は、Unicodeのコードポイントに対応するASCII文字として解釈されるべきであるが含まれています。
4.1クラスファイルの構造
クラスファイルは、単一のクラスファイル構造で構成されます。
クラスファイル{ U4の魔法。 U2のminor_version; U2のmajor_version; U2のconstant_pool_count。 constant_pool cp_info [constant_pool_count - 1 ]。 U2のaccess_flags。 U2のthis_class。 U2のsuper_class。 U2のinterfaces_count。 U2インターフェイス[interfaces_count]。 U2のfields_count。 フィールドfield_info [fields_count]。 U2のmethods_count。 method_info方法[methods_count]。 U2のattributes_count。 attribute_infoは[attributes_count]属性。 }
クラスファイルの構造の説明は次のよう:
- 魔法
魔法のエントリは、クラスファイル・フォーマットを識別するマジックナンバーを定義し、その値は0xCAFEBABEです。
- minor_version、major_version
minor_versionと値はマイナーバージョン番号とメジャーバージョン番号のクラスファイルmajor_versionを表します。クラスファイルのマイナーバージョン番号と一緒にメジャーバージョン番号のバージョン番号を確認します。クラスファイルのメジャーバージョン番号がMであれば、マイナーバージョン番号をm、我々はこのクラスファイルのバージョン番号にあるmmです。したがって、クラスファイル形式のバージョン番号は、例えば、1.5 <2.0 <2.1辞書によって順序付けされてもよいです。
vは(Mi.0は、仮想マシンがバージョン番号をサポートしていMj.mする)一つの連続範囲Mi.0≤v≤Mj.m時間である場合にのみ場合は、Java仮想マシンの実装では、クラスファイル形式のVバージョンをサポートすることができます。Java仮想マシンは、Java SEプラットフォームのリリース・レベルは、範囲を決定する責任があり、次の。
OracleのJava仮想マシンの実装クラスファイル形式のサポートのJDKのバージョン1.0.2は、45.0 45.3のクラスが含まれています。JDK1.1。*バージョン(含む)45.65535から45.0の範囲内のクラスファイル形式のバージョンをサポートしています。≧2の場合は、JDKのバージョンは45.0 k.0 + 44の範囲1.kクラスファイル形式のバージョンをサポートしています。
- constant_pool_count
1 constant_pool_count constant_poolテーブルエントリの数です。Constant_pool指数が0より大きく、constant_pool_countが有効であるよりも小さい、longとdouble定数に加えて、特定の4.4.5を参照してください。
- constant_pool []
constant_poolは、様々なストリング定数、クラスおよびインタフェース名、フィールド名、及びクラスファイル構造と下部構造で言及他の定数を示したテーブル構造です。
1からconstant_pool_count_1にConstant_poolテーブルインデックス。
- access_flags
Access_flagsマスクは、クラスまたはインタフェースの属性とアクセス権を表す値を識別する。以下の表に意味することは、各識別された4.1Aのために設けられています。
表4.1Aおよびアクセス修飾子ロゴ
識別名 | 値 | 意味 |
---|---|---|
ACC_PUBLIC |
0x0001 | 宣言public ;クラスは、パッケージの外側にアクセスすることができます。 |
ACC_FINAL |
0x0010 | 宣言されfinal 、サブクラスを許可していません。 |
ACC_SUPER |
0x0020に | あなたは、スーパークラスのメソッドにinvokspecialial命令、特別な処理を呼び出すとき。 |
ACC_INTERFACE |
0x0200 | インターフェイスではなく、クラスです |
ACC_ABSTRACT |
0x0400 | 声明为 abstract ;これは、インスタンス化することはできません。 |
ACC_SYNTHETIC |
0x1000番地 | 合成は、宣言された、ソースコードが存在しません。 |
ACC_ANNOTATION |
0x2000で | これは、注釈のタイプです。 |
ACC_ENUM |
0x4000の | 列挙型です。 |
インターフェイスは、このIDが設定されていない場合は、クラスファイルは、クラスの定義ではなく、インタフェースで、ACC_INTERFACE IDを設定することで区別されます
ACC_INTERFACEフラグが設定されている場合ACC_ABSTRACTアイデンティティはまた、ACC_FINALを設定する必要があり、その後、ACC_SUPERとACC_ENUMを設定することが許可されていません。
ACC_INTERFACE IDが設定されていない場合、ACC_ANNOTATION以外のアイデンティティを設定することができます。しかし、そのようなクラス・ファイルが同時にACC_FINALとACC_ABSTRACTを設定することはできません。
それはinvokespecial命令(§invokespecial)によってこのクラスまたはインタフェースに表示されるかを示すACC_SUPERフラグの2つの代替セマンティクスを示しています。コンパイラのJava仮想マシンの命令セットはACC_SUPERフラグを設定する必要があります。後でのJava SE 8とにかかわらず、クラスファイルとクラスファイルの実際の値のフラグのどのバージョンの、各クラスファイルにACC_SUPERフラグを設定するには、Java仮想マシンで。
ACC_SUPERフラグは、Javaプログラミング言語コンパイラのコードでコンパイルされ、古いとの下位互換性のためであります。フラグが設定されている場合、JDK 1.0.2以前のバージョンでは、コンパイラは意味が指定されていないシンボルACC_SUPERを表し、アクセスフラグを生成し、OracleのJava仮想マシンの実装はフラグを無視します。
ACC_SYNTHETIC識別子は、クラスまたはインタフェースは、コンパイラによって生成され、元のコードで表示されていない示します。
注釈タイプはACC_ANNOTATIONフラグが設定されている場合、ACC_INTERFACEアイデンティティも設定する必要があり、ACC_ANNOTATION IDを設定する必要があります。
ACC_ENUMロゴは、このクラスまたはその親クラスが列挙型として宣言されていることを示しています。
access_flags 将来の使用のために予約されたビットの表4.1Aのすべての未割り当てを。プロダクションクラスファイル、彼らは0に設定する必要があり、Java仮想マシンの実装は、それらを無視する必要があります。
- このクラス
This_class値は有効なインデックスconstant_poolテーブルでなければなりません。この位置でconstant_poolインデックスエントリがCONSTAN_Class_info構造である必要があり、このクラスは、クラスまたはインタフェース定義ファイルを表しています。
- super_class
クラスの場合、値は有効なインデックスsuper_class 0またはconstant_poolでなければなりません。Super_class値が0でない場合は、インデックス内のconstant_poolエントリは位置CONSTANT_Class_info構造でなければなりませんが、このクラス定義ファイルに直接の親クラスを表します。その直接の親とそのすべての親クラスのクラスファイル構造がaccess_flags ACC_FINAL識別に提供することはできません。
値が0の場合Super_class、その後、このクラスは親クラスやインタフェースのための直接的なサポートを持つ唯一のものであるObjectクラスでなければなりません。
インターフェースの場合、値は有効なインデックスsuper_class constan_poolでなければならず、インデックスは、オブジェクトクラスを表す、対応するエントリCONSTAN_Class_info構造でなければなりません。
- interfaces_count
Interfaces_count値は、直接の親の数をインターフェースするクラスまたはインタフェースを表します。
- インターフェイス[]
各値インタフェース・アレイはconstant_poolの有効なインデックスでなければなりません。インターフェースのconstant_pool [i]は、インデックス値に対応する親と直接インターフェースするクラスまたはインタフェースを表すエントリCONSTANT_Class_info構造でなければならず、いくつかは、元のコードに左から順に与えます。
- fields_count
Fields_count値は、テーブルfield_info構造内のフィールドの数を表します。クラスまたはインタフェースによって表さfield_info構造は、クラス、インスタンス変数を含むすべてのフィールドを宣言する。
- フィールド[]
フィールドは、テーブル内の各値は、フィールド内のクラスまたはインタフェースの完全な説明を考慮すると、field_indo構造でなければなりません。テーブルのフィールドは、このクラスまたはインタフェースで宣言されたフィールドのみが含まれています。親フィールドから継承することは、親クラスまたはインタフェースが含まれていません。
- methods_count
値のMethods_count数を表クラスのメソッドで指定された構造をmethod_info
- メソッド[]
方法は、テーブル内の各値は方法の完全な説明でmethod_info構造、method_info所与のクラスまたはインタフェースでなければなりません。ACC_NATIVEとACC_ABSTRACHアイデンティティのmetchod_info構造access_flagsが設定されていない場合、この方法の実現には、Java仮想マシン命令が提供されますです。
method_info構造は、このクラスまたはインタフェースのすべてのメソッド、インスタンスメソッド、クラスメソッド、インスタンスの初期化方法、及びクラスおよびインタフェースの任意の初期化処理を表します。親テーブルから継承されたメソッドは、親クラスまたはインタフェースのメソッドが含まれていません。
- atttibutes_count
Attribute_count値はattrubuteテーブルのこのクラスの属性の数を示します。
- 属性[]
表中の各値は、構造attribute_info属性です。
表4.7-Cは、本明細書の発生はクラスファイルの属性テーブル構造の属性を定義示します。、
定義については、属性の§4.7で与えられたルールの属性テーブルのクラスファイル構造に表示されます。
クラスファイルの構造に関連するルールの属性テーブルを所定の非定義された属性は§4.7.1に記載されています。
4.2内部名を表します
4.2.1バイナリクラスおよびインタフェースを名前
クラスファイルの構造は、(JLS§13.1)の完全修飾名(バイナリ名)と呼ばれ、常にバイナリ形式で表現されたクラスとインタフェースの名前で表示されます。これらの名前は、常にCONSTANT_Utf8_info構造(4.4.7項)として表現されているので、あなたは全体のUnicode文字スペースから(なし、さらに拘束された場合)を取得することができます。そして、インターフェース構造のバイナリクラス名は、その記述子(4.3)を構成する、CONSTANT_NameAndType_infoによって参照されますが、これらの名前を参照することによって実現されるそれらに構造をCONSTAN_Class_info参照してください。
歴史的な理由のためのさまざまな文法や構文JLS§13.1バイナリ名は、レコード内のバイナリファイル名のクラス構造で表示されます。区切られたASCII識別名バイナリピリオド(。)を構成し、この内部形式にASCIIスラッシュ(/)によって置き換えられます。それ自体は非修飾名識別子(セクション4.2.2)でなければなりません。
たとえば、Threadクラス普通のバイナリ名はjava.lang.Threadのです。クラスファイル形式の記述子で使用される内部形式、スレッドのクラス名への参照を実現するためのjava / LANG /スレッドCONSTANT_Utf8_info構造を表す文字列。
4.2.2非修飾名
メソッド、フィールド、非修飾名(非修飾名)のストレージを使用して、ローカル変数およびパラメータ名。非修飾名は、少なくともUnicodeコードポイントが含まれている必要があり、ASCII文字;. [/(即ちドット、セミコロン、左括弧、スラッシュ)を含んでいてもよいです。
特別な添加<初期化>と<clinit>(§2.9)、それらはASCII文字を含むことができません<または>(すなわち、左または右アングルブラケットアングルブラケット)に加えて、この方法は、さらに限定名、メソッド名。
フィールド名またはインターフェイスメソッドの名前はの<init>または<clinit>できることに注意してください、しかし、あなたは<clinit>命令の参照を呼び出すことができる方法はありません、唯一のinvokespecial命令(§invokespecialは)への<init>参照することができます。
4.3記述子
記述子は、フィールドやメソッドタイプ文字列です。修正UTF-8文字列(4.4.7項)クラスファイル形式で表現を使って記述子が、(なし、さらに制限ワードであれば)全体のスペース文字のUnicode文字を使用することが可能です。
4.3.1構文記法
記述子は、特定の構文を表すために使用されます。構文のセットがどのように様々な製品の文字の列が構文的に正しい記述について説明しています。構文ターミネータ固定幅フォント、イタリック非終端。非終端記号は、コロン後の非末端名によって定義される定義を示しています。右一つ以上の非交換ターミネーターのコロンのは、連続して配置されています。
これは、0回以上を意味右{X}に現れます。
次のラインターミネータによって、または複数のラインに示される右側の語句(の1つ)それぞれが任意に定義されています。
4.3.2フィールド記述子
フィールド記述子タイプは、クラス、インスタンス、またはローカル変数を示します。
FieldDescriptor: FIELDTYPE FIELDTYPE: BaseType のObjectType のArrayType BaseType: (の1つ) BCDFIJSZ のObjectType: Lのクラス名。 ArrayType: [COMPONENTTYPE COMPONENTTYPE: FIELDTYPE
BaseType文字、ObjecType Lと、とのArrayTypeの[すべてのASCII文字。
クラス名は、バイナリクラスまたはインタフェース名の内部形態を表します。
フィールド記述子テーブル4.3-Aを意味タイプ
寸法タイプを有する場合にのみ255以下で表されるタイプのフィールド記述子のアレイ。
表4.3-意味フィールド記述子
フィールドタイプ項目 | タイプ | 意味 |
---|---|---|
B |
byte |
符号付きバイト |
C |
char |
UTF-16でエンコードされた基本多言語面でのUnicode文字コード・ポイント、 |
D |
double |
倍精度浮動小数点値 |
F |
float |
単精度浮動小数点値 |
I |
int |
整数 |
J |
long |
長整数 |
L クラス名 ; |
reference |
クラスのインスタンス クラス名 |
S |
short |
短い署名 |
Z |
boolean |
true 若しくは false |
[ |
reference |
1つの配列の次元 |
int型記述子のWordのインスタンス変数はIです。
フィールドの例としては、Object型の変数はLjava /ラング/オブジェクトである記述子、。クラスオブジェクトのバイナリ名の内部で使用することに注意してください。
ダブルワード記述子タイプ多次元配列[] [] []インスタンス変数は、[[[Dであります
4.3.3メソッドの記述
方法の記述は、ゼロ以上のパラメータ記述子、使用される方法の種類を示すパラメータを含み、方法(もしあれば)によって返される値のタイプを示す記述子を返します。
MethodDescriptorを: ({ParameterDescriptor})ReturnDescriptor ParameterDescriptor: FIELDTYPE ReturnDescriptor: FIELDTYPE VoidDescriptor VoidDescriptor: V
記号Vは、(ボイドの結果である)値を返さない方法を意味します。
この方法の記述: オブジェクトm(INT Iは、ダブルD、スレッドT){...}が ある: (IDLjava / LANG /スレッド;)Ljava /ラング/オブジェクト。 なお、バイナリスレッド名とOBJECの使用内部形式。
メソッド記述子が有効である場合には、255未満のその対応方法の全体の長さのパラメータリストは、方法およびインタフェースのメソッドのための強さが余分にこれを考慮する必要があります。パラメータリスト長算出ルールを次のように2の各クラスパラメータ長い二重の長さを、残りは全長がすべてのメソッドパラメータおよび長さの引数リストに等しく、1です。
かかわらず、記載またはインスタンスメソッドがクラスメソッドであるメソッドの、メソッド記述子は同じです。この方法は、この例に合格したが、指示物体は、その予想されるパラメータに加えて、このことは、プロセスの記述に反映されていない、参照方法と呼ばれています。この方法の例としては、暗黙のうちに(§2.6.1、§4.11)渡されたJava仮想マシン命令を呼び出すことによって参照されています。