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

クラスファイルの構造

クラスファイルのクラス構造

単一のクラスまたはインタフェースに対応する任意のクラスファイル定義情報は、必ずしもファイルに定義されたクラスまたはインタフェースを持たない(そのようなクラスは、クラスローダによって直接生成することができるように)。クラス・ファイルは、ベースユニットの8ビット・バイトのセットにバイナリストリームは、データの正確な順序は、クラスファイル内にコンパクトに配置されています。クラスファイルフォーマットの擬似C言語に似た2つのデータ型を含むデータを格納する構造体への構造:符号なしとテーブル。
U1、U2、U4、符号なし1,2,4,8バイトを表すためにU8への基本的なデータ型に属し符号なし。図面、参照インデックス、符号化された値またはストリング構成UTF-8に記載の値の数を記述するために使用することができます。
表符号なしの数は、テーブルのまたは複合データ型、「_info」最後まですべてのテーブルの習慣を構成する他のデータ項目として複数です。表は、階層関係に沿ってデータの構造を記述するために使用されます。

クラスファイルのマジックナンバーのバージョン

ファイルは仮想ファイルであるかどうかを確認するために、クラス数(マジックナンバー)マジックと呼ばれるファイルの最初の4つのバイトは、クラスで受け入れられます。マジッククラス値ファイルは、次のとおりです。0xCAFEBABE、Javaまたはそれが確認された「オーク」のマジックナンバー(コーヒー赤ちゃん?)。
4つのバイトは、クラスのファイルのバージョン番号に格納された後、第5および第6バイト目は、マイナーバージョン番号(マイナーバージョン)、7番8はメジャーバージョン(メジャーバージョン)です。Javaのバージョン番号が45の開始からのものであり、大きな1.1リリースのメジャーバージョン番号が1までインクリメントされた後、高JDKのバージョンは、クラスファイルの下位互換性が、それ以降のバージョンを実行することはできません。

定数プール

メジャーとマイナーバージョン番号の後に時定数プール、倉庫リソースクラスファイルのうち、データのほとんどのタイプに関連した他の項目、だけでなく、最大のプロジェクトのクラスファイル・スペースの1を占めます。定数の数が固定されていないので、定数プールのカウント値(constant_pool_count)の容量を表す定数プールU2データ型の入り口を、防止する必要があります。
リテラル(リテラル)とシンボリック参照(シンボリック参照):2つの定数の種類を格納するためのメイン定数プール。リテラルは近づくなテキスト文字列としてJava言語で一定レベルの概念に、最終的にというように一定の値として宣言しました。シンボル参照コンパイラの理論は、以下の3つの定数を含む領域の概念に属しています:

  • クラスやインタフェースの完全修飾名(完全修飾名)
  • 名前と記述子フィールド(記述子)
  • メソッド名と記述子

javacのJavaのコードのコンパイル時には、CやC ++とは異なり、このステップを接続しますが、仮想マシンがクラスファイルをロードされたときに動的に接続されています。仮想マシンが実行され、対応するシンボルは、クラスが作成されたときに解決または実行されている定数プール参照から得られる特定のメモリアドレスに変換されます。

アクセスフラグ

2バイトのクラスまたはインタフェースレベルのアクセス情報の数を識別するために、アクセスフラグ(access_flag)を表す直後定数プール。含む:クラスまたはインタフェース、抽象的かどうか、公共のかどうか、最終的なようにするかどうか。

フラグ名 フラグ値 意味
ACC_PUBLIC 0x0001 かどうかは、公開
ACC_FINAL 0x0010 最終的かどうか
ACC_SUPER 0x0020に セマンティック変更がJDK1.0.2で発生したためかどうかは、それほどコンパイルされたクラスの後に、このフラグがtrueでなければならない、新しい意味論invokespecialバイトコード命令の使用を許可します
ACC_INTERFACE 0x0200 インタフェースかどうか
ACC_ABSTRACT 0x0400 それは抽象クラスであるかどうか
ACC_SYNTHETIC 0x1000番地 かどうかは、コンパイラによって自動的に生成しました
ACC_ANNOTATION 0x2000で 注釈クラスかどうか
ACC_ENUM 0x4000の 列挙型かどうか

例えば、ACC_PUBLIC ACC_SUPEフラグので、一般市民のカテゴリは、他の偽旗、本当です。だから、値がaccess_flags:0x0001のは、| = 0x0021 0x0020に
5の前には、定義をマークし、Java仮想マシンの仕様、3つの背後の後に1.5の増加です。

クラスインデックス、および親クラスのインターフェイスインデックスセットのインデックス

クラスインデックス(this_class)親インデックス(super_class)は、インデックスは、データセットのタイプU2の群の界面(インターフェイス)を設定すると、U2のデータ型です。アクセスフラグの後ろのために。

タイプ 名前 数量
U2 クラスインデックス 1
U2 親インデックス 1
U2 [N] インターフェイスインデックス n個

テーブルのフィールドセット

変数を記述するために使用されるテーブルのフィールド(field_info)は、クラスまたはインタフェース内で宣言されました。フィールドは、クラスのインスタンス変数とクラス変数レベルを含むが、メソッド内で宣言されたローカル変数を含んでいません。フラグが使用される変性剤の量は、定数プール内の定数を記述するために使用されるフィールド名のタイプを示します。
access_flag意味

フラグ名 フラグ値 意味
ACC_PUBLIC 0x0001 かどうかは、公開
ACC_PRIVATE 0×0002 プライベートかどうか
ACC_PROTECTED 0x0004は それが保護されているかどうか
ACC_STATIC 0x0008で それは静的であるかどうか
ACC_FINAL 0x0010 最終的かどうか
ACC_VOLATILE 0x0040が 揮発性かどうか
ACC_TRANSIENT 0x0080 一過性かどうか
ACC_SYNTHETIC 0x1000番地 かどうかは、コンパイラによって自動的に生成しました
ACC_ENUM 0x4000の 列挙型かどうか
タイプ 名前 数量
U2 access_flag 1
U2 name_index 1
U2 descriptor_index 1
U2 attributes_count 1
attribute_info 属性 attributes_count

表収集方法

メソッドテーブル(method_info)は、クラスまたはインタフェースで宣言されたメソッドを記述しています。
揮発性キーワードとキーワード過渡方法を変更することができないので、アクセスフラグテーブル法はACC_VOLATILE標識とACC_TRANSIENTフラグないからです。これとは対照的に、抽象strictfpとして、ネイティブ、同期およびキーワードは方法を変更することができ、アクセスフラグテーブル方式はACC_SYNCHRONIZED、ACC_NATIVE、ACC_STRICTFPとACC_ABSTRACTフラグを追加します。

フラグ名 フラグ値 意味
ACC_PUBLIC 0x0001 かどうかは、公開
ACC_PRIVATE 0×0002 プライベートかどうか
ACC_PROTECTED 0x0004は それが保護されているかどうか
ACC_STATIC 0x0008で それは静的であるかどうか
ACC_FINAL 0x0010 最終的かどうか
ACC_SYNCHRONIZED 0x0020に それが同期されているかどうか
ACC_BRIDGE 0x0040が かどうかは、コンパイラをブリッジする方法
ACC_VARARGS 0x0080 不確実なパラメータを受け入れるかどうか
ACC_NATIVE 0x0100 かどうかはネイティブ
ACC_ABSTRACT 0x0400 抽象的かどうか
ACC_STRICTFP 0x0800で かどうかはstrictfp
ACC_SYNTHETIC 0x1000番地 かどうかは、コンパイラによって自動的に生成しました
タイプ 名前 数量
U2 access_flag 1
U2 name_index 1
U2 descriptor_index 1
U2 attributes_count 1
attribute_info 属性 attributes_count

プロパティシートコレクション

属性表(attribute_info)之前反复出现,在Class文件、字段表、方法表都可以携带字节的属性表集合,用于描述某些场景专有信息。
顺序、长度、内容的要求不像前面那么严格。
不要求各个属性表具有严格顺序,并且只要不与已有属性名重复,任何人 实现的编译器都可以向属性表中写入自己定义的属性信息,Java虚拟机运行时会忽略掉它不 认识的属性。

属性名称 使用位置 含义
Code 方法表 Java代码编译成的字节码指令
ConstantValue 字段表 final关键字定义的常量值
Deprecated 类、方法表、字段表 声明为deprecated的方法和字段
Exceptions 方法表 方法抛出的异常
EnclosingMethod 类文件 仅当一个类为局部类或者匿名类才有这个属性,用于标识这个类所在的外围方法

...

属性表结构:

类型 名称 数量
u2 attribute_name_index 1
u4 attribute_length 1
u1 info attribute_length

完整结构描述

表用于描述有层次关系的符合结构的数据,整个Class文件本质上就是一张表,其构成成分就是如下的数据项:

数据类型 名称 数量
u2 attribute_name_index 1
u4 attribute_length 1
u2 max_stack 1
u2 max_locals 1
u4 code_length 1
u1 code code_length
u2 exception_table_length 1
exception_info exception_table exception_table_length
u2 attribute_count 1
attribute_info attributes attribute_count

实例

为了能够更好的理解,我们拿一个实际的类文件来分析一下。

源码

package com.software5000.base.jsql;

public class TestClass {
    public String strField;

    public int intField;

    public String getStrField() {
        return strField;
    }

    public void setStrField(String strField) {
        this.strField = strField;
    }

    public int getIntField() {
        return intField;
    }

    public void setIntField(int intField) {
        this.intField = intField;
    }
}

这是一个很简单的测试类,两个属性,以及对应的getter/setter方法。

Class文件

Class文件

分析

针对类文件以及前面的概念对比分析

魔数、Class版本

CAFEBABE - 魔数
00000034 - 版本 52 :jdk 1.8

常量池长度

0020 - 32-1 长度31个常量项

常量池内容

01——
0A tag表示 constant_methodref_info
0005 index no. 5 contant_class_info
001B index no. 27 constant_nameandtype

02——
09 tag constant_fieldref_info
0004 index no.4 constant_class_info
001C index no.28 constatn_nameandtype

03——
09 tag constant_fieldref_info
0004 index no.4 constant_class_info
001D index no.29 constatn_nameandtype

04——
07 tag constant_class_info
001E index no.30

05——
07 tag constant_class_info
001F index no.31

06——
01 tag constant_utf8_info
0008 length 8 byte
7374 7246 6965 6C64 strField

07——
01 tag constant_utf8_info
0012 length 18 byte
4C6A 6176 612F 6C61 6E67 2F53 7472 696E 673B Ljava/lang/String;

08——
01 tag constant_utf8_info
0008 length 8 byte
696E 7446 6965 6C64 intField

09——
01 tag constant_utf8_info
0001 length 1 byte
49 I

10——
01 tag constant_utf8_info
0006 length 6 byte
3C69 6E69 743E

11——
01 tag constant_utf8_info
0003 length 3 byte
2829 56 ()V

12——
01 tag constant_utf8_info
0004 length 4 byte
436F 6465 Code

13——
01 tag constant_utf8_info
000F length 15 byte
4C69 6E65 4E75 6D62 6572 5461 626C 65 LineNumberTable

14——
01 tag constant_utf8_info
0012 length 18 byte
4C6F 6361 6C56 6172 6961 626C 6554 6162 6C65 LocalVariableTable

15——
01 tag constant_utf8_info
0004 length 4 byte
7468 6973 this

16——
01 tag constant_utf8_info
0026 length 38 byte
4C63 6F6D 2F73 6F66 7477 6172 6535 3030 302F 6261 7365 2F6A 7371 6C2F 5465 7374 436C 6173 733B Lcom/software5000/base/jsql/TestClass;

17——
01 tag constant_utf8_info
000B length 11 byte
67 6574 5374 7246 6965 6C64 getStrField

18——
01 tag constant_utf8_info
0014 length 20 byte
2829 4C6A 6176 612F 6C61 6E67 2F53 7472 696E 673B ()Ljava/lang/String;

19——
01 tag constant_utf8_info
000B length 11 byte
7365 7453 7472 4669 656C 64 setStrField

20——
01 tag constant_utf8_info
0015 length 21 byte
284C 6A61 7661 2F6C 616E 672F 5374 7269 6E67 3B29 56 (Ljava/lang/String;)V

21——
01 tag constant_utf8_info
000B length 11 byte
6765 7449 6E74 4669 656C 64 getIntField

22——
01 tag constant_utf8_info
0003 length 3 byte
2829 49 ()I

23——
01 tag constant_utf8_info
000B length 11 byte
7365 7449 6E74 4669 656C 64 setIntField

24——
01 tag constant_utf8_info
0004 length 4 byte
2849 2956 (I)V

25——
01 tag constant_utf8_info
000A length 10 byte
536F 7572 6365 4669 6C65 SourceFile

26——
01 tag constant_utf8_info
000E length 14 byte
5465 7374 436C 6173 732E 6A61 7661 TestClass.java

27——
0C tag constant_Name-andtype-info
000A index no.10
000B index no.11

28——
0C tag constant_Name-andtype-info
0006 index no.6
0007 index no.7

29——
0C tag constant_Name-andtype-info
0008 index no.8
0009 index no.9

30——
01 tag constant_utf8_info
0024 length 36 byte
5636F 6D2F 736F 6674 7761 7265 3530 3030 2F62 6173 652F 6A73 716C 2F54 6573 7443 6C61 7373 com/software5000/base/jsql/TestClass

31——
01 tag constant_utf8_info
0010 length 16 byte
6A61 7661 2F6C 616E 672F 4F62 6A65 6374 java/lang/Object

访问标志

0021 访问标志 (ACC_PUBLIC,ACC_SUPER两个标志位为真)

类索引、父类索引、接口索引

0004 类索引 no.4
0005 父类索引 no.5
0000 接口索引集合 0

字段表集合

0002 fields_counts 2个字段表数据

No.1 field
0001 access_flag public
0006 index no.6 name_index
0007 index no.7 descriptor_index
0000 attributes_count

No.2 field
0001 access_flag public
0008 index no.8 name_index
0009 index no.9 descriptor_index
0000 attributes_count

方法表集合

0005 methods_count 5个方法

No.1 method
0001 access_flag public
000A index no.10 name_index
000B index no.11 descriptor_index ()V
0001 attributes_count 1个
000C attributes_info LineNumberTable

剩余的待进一步补充。。。

总结

Class文件的结构理解,说实话对于编码或者性能优化等方面没有什么特别大的帮助,但是能够帮我们更好的理解Java及其设计的思想。我们从Class文件的结构设计中也能够学习到一些模式,这些东西可能会在后续的研发过程提供一些解决问题或者设计方案的思路。
这才是最重要的。

おすすめ

転載: www.cnblogs.com/pluto4596/p/11870986.html