- クラスファイルの構造
- 概要
- 2つのクラスファイル構造の概要
- 2.1マジックナンバー
- 2.2クラスファイルのバージョン
- 2.3定数プール
- 2.4アクセスのロゴ
- 2.5現在のクラスのインデックス、および親クラスインターフェースインデックスセットの指標
- フィールド・テーブルは、2.6を設定しました
- 2.7テーブルのメソッドのセット
- 2.8属性テーブルコレクション
クラスファイルの構造
概要
Javaでは、JVMコードが理解できると呼ばれている字节码
(つまり、拡張子 .class
のファイル)、それだけで仮想マシンのために、任意の特定のプロセッサに直面していません。ポータブルインタプリタ言語の機能を維持しながら、Javaのバイトコード言語を経由して、ある程度、従来のインタプリタ言語の問題の低効率を解決します。バイトコードは、特定のマシンを対象とされていないため、より効率的なJavaプログラムを実行している、そしてときに、そのため、Javaプログラムを再コンパイルする必要は多くの異なるコンピュータのオペレーティング・システム上で実行することはできません。
Clojureの(Lispの言語の方言)、Groovyの、スカラ座や他の言語は、Java仮想マシン上で実行されています。次の図は、異なる言語が異なるコンパイラ異常でコンパイルされ示し.class
Java仮想マシン上のファイルの最終実行。.class
バイナリ形式のファイルを使用することができます WinHexの ビューを。
言うことができる.class
ファイルは、Java仮想マシン間の重要な橋の異なる言語であるが、クロスプラットフォームのJavaが非常に重要な理由をサポートしています。
2つのクラスファイル構造の概要
Java仮想マシン仕様、単一のクラスファイルのクラスファイル構造:
{クラスファイル
U4マジック; ロゴ//クラスファイル
U2のminor_version; 小の//クラスバージョン番号 U2のmajor_version、メジャーバージョン番号constant_pool_count U2の//クラス; //定数プールconstant_pool番号[constant_pool_count cp_info - 1]; // ;定数プールU2 access_flags //クラスアクセスthis_classマーカーU2; //現在のクラスsuper_classのU2; //親interfaces_countのU2; //インターフェイスインターフェイスU2 [interfaces_count]; ; //クラスは、複数のインターフェイスのfields_countのU2を実装することができます/ / field_infoフィールドクラスフィールド[fields_count]属性ファイル; //クラスのフィールドU2のmethods_countがあるかもしれません。ファイルの数//クラスメソッドメソッド[methods_count] method_info; //クラスはメソッドのU2のattributes_countを複数持つことができます。; //このような属性の属性の数は、[attributes_count] attribute_infoテーブル属性} //セット属性テーブル
関連するコンポーネントのクラスファイル構造の一部について、次の詳細が表示されます。
クラスファイルのバイトコードの構造組織図は(以前にオンラインに保存、非常に良い、元のソース不明):
2.1マジックナンバー
U4マジック; ロゴ//クラスファイル
各ファイルのクラス最初の4つのバイトはマジックナンバー(マジックナンバー)と呼ばれ、その唯一の目的は、ファイルが、クラスの仮想マシンを受け取ることができるファイルであるかどうかを判断することです。
プログラマは、多くの場合、いくつかの特別な番号は固定ドキュメントタイプやその他の特別な意味を示す使用するようにしたいです。
2.2クラスファイルのバージョン
minor_versionのU2; //小型のクラスのバージョン番号
U2のmajor_version; メジャーバージョン番号の//クラス
次に、ストレージの4バイトのマジックナンバーは、クラスファイルのバージョン番号である:第五及び第六は、マイナーバージョン番号、第7及び第8のメジャーバージョン番号です。
Java仮想マシンの高性能バージョンは、コンパイラ生成されたクラスファイルの低いバージョンを実行することができますが、Java仮想マシンの下位バージョンでは、コンパイラが生成したクラスファイルの高いバージョンを実行することはできません。だから、私たちは実際にJDKのバージョンと一貫性のある生産環境のJDKのバージョンの発展を確保するために開発されたとき。
2.3定数プール
constant_pool_countのU2; //定数プール番号
constant_pool [constant_pool_count cp_info - 1]; //定数プール
紧接着主次版本号之后的是常量池,常量池的数量是 constant_pool_count-1(常量池计数器是从1开始计数的,将第0项常量空出来是有特殊考虑的,索引值为0代表“不引用任何一个常量池项”)。
常量池主要存放两大常量:字面量和符号引用。字面量比较接近于 Java 语言层面的的常量概念,如文本字符串、声明为 final 的常量值等。而符号引用则属于编译原理方面的概念。包括下面三类常量:
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
常量池中每一项常量都是一个表,这14种表有一个共同的特点:开始的第一位是一个 u1 类型的标志位 -tag 来标识常量的类型,代表当前这个常量属于哪种常量类型.
类型 | 标志(tag) | 描述 |
---|---|---|
CONSTANT_utf8_info | 1 | UTF-8编码的字符串 |
CONSTANT_Integer_info | 3 | 整形字面量 |
CONSTANT_Float_info | 4 | 浮点型字面量 |
CONSTANT_Long_info | 5 | 长整型字面量 |
CONSTANT_Double_info | 6 | 双精度浮点型字面量 |
CONSTANT_Class_info | 7 | 类或接口的符号引用 |
CONSTANT_String_info | 8 | 字符串类型字面量 |
CONSTANT_Fieldref_info | 9 | 字段的符号引用 |
CONSTANT_Methodref_info | 10 | 类中方法的符号引用 |
CONSTANT_InterfaceMethodref_info | 11 | 接口中方法的符号引用 |
CONSTANT_NameAndType_info | 12 | 字段或方法的符号引用 |
CONSTANT_MothodType_info | 16 | 标志方法类型 |
CONSTANT_MethodHandle_info | 15 | 表示方法句柄 |
CONSTANT_InvokeDynamic_info | 18 | 表示一个动态方法调用点 |
.class
文件可以通过javap -v class类名
指令来看一下其常量池中的信息(javap -v class类名-> temp.txt
:将结果输出到 temp.txt 文件)。
2.4 访问标志
在常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口,是否为 public 或者 abstract 类型,如果是类的话是否声明为 final 等等。
类访问和属性修饰符:
我们定义了一个 Employee 类
package top.snailclimb.bean;
public class Employee {
... }
通过javap -v class类名
指令来看一下类的访问标志。
2.5 当前类索引,父类索引与接口索引集合
u2 this_class;//当前类
u2 super_class;//父类
u2 interfaces_count;//接口 u2 interfaces[interfaces_count];//一个雷可以实现多个接口
类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了 java.lang.Object
之外,所有的 java 类都有父类,因此除了 java.lang.Object
外,所有 Java 类的父类索引都不为 0。
接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按implents
(如果这个类本身是接口的话则是extends
) 后的接口顺序从左到右排列在接口索引集合中。
2.6 字段表集合
u2 fields_count;//Class 文件的字段的个数
field_info fields[fields_count];//一个类会可以有个字段
字段表(field info)用于描述接口或类中声明的变量。字段包括类级变量以及实例变量,但不包括在方法内部声明的局部变量。
field info(字段表) 的结构:
- access_flags: 字段的作用域(
public
,private
,protected
修饰符),是实例变量还是类变量(static
修饰符),可否被序列化(transient 修饰符),可变性(final),可见性(volatile 修饰符,是否强制从主内存读写)。 - name_index: 对常量池的引用,表示的字段的名称;
- descriptor_index: 对常量池的引用,表示字段和方法的描述符;
- attributes_count: 一个字段还会拥有一些额外的属性,attributes_count 存放属性的个数;
- attributes[attributes_count]: 存放具体属性具体内容。
上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适合使用标志位来表示。而字段叫什么名字、字段被定义为什么数据类型这些都是无法固定的,只能引用常量池中常量来描述。
字段的 access_flags 的取值:
2.7 方法表集合
u2 methods_count;//Class 文件的方法的数量
method_info methods[methods_count];//一个类可以有个多个方法
methods_countメソッドテーブルmethod_info表現しつつ、多数の方法を表します。
クラスファイルの格納フォーマットについて説明し、フィールドの使用方法の説明はほとんど同じ方法です。順次アクセスフラグを含むフィールド構成表テーブルとして方法、インデックス、インデックス記述子、いくつかのセット属性テーブルの名前。
method_info(表法)構造:
値のaccess_flagメソッドテーブル:
注:のでvolatile
改質及びtransient
改質剤は方法を変更することができない、アクセスフラグテーブルの方法は、これら二つの符号に対応していないが、追加synchronized
、native
、abstract
及び他のキー修飾方法をので、シンボルに対応するこれらのキーワードのためのより多くがあります。
2.8属性テーブルコレクション
U2のattributes_count; 属性など//属性テーブルの数
[attributes_count]属性attribute_info; //属性セットテーブル
特定のシナリオは、独自の情報を記述するために、クラスファイル属性テーブル、フィールドテーブル、方法テーブルの独自のセットをもたらすことができます。クラスファイルと属性テーブルを設定し、異なる長さやコンテンツの制限を必要な他のデータ項目の順序が少し緩いです、属性テーブルは、もはやそれぞれが厳密な順序を必要としない、と彼らは、既存の属性名を複製し、任意のはありませんコンパイラは属性テーブルに属性情報の独自の定義を書くことができます達成するため、無視は、Java仮想マシンが実行されている認識していない属性。
出典:https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/jvm/%E7%B1%BB%E6%96%87%E4%BB%B6%E7%BB%93%E6 %9E%84.md