class文件示例

public class TestClass {
    private int m;
    public int inc() {
        return m+1;
    }
}
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];
}
public class com.enjoy.learn.core.oop.method.TestClass
  minor version: 0
  major version: 52
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #3                          // com/enjoy/learn/core/oop/method/TestClass
  super_class: #4                         // java/lang/Object
  interfaces: 0, fields: 1, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #4.#18         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#19         // com/enjoy/learn/core/oop/method/TestClass.m:I
   #3 = Class              #20            // com/enjoy/learn/core/oop/method/TestClass
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               m
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/enjoy/learn/core/oop/method/TestClass;
  #14 = Utf8               inc
  #15 = Utf8               ()I
  #16 = Utf8               SourceFile
  #17 = Utf8               TestClass.java
  #18 = NameAndType        #7:#8          // "<init>":()V
  #19 = NameAndType        #5:#6          // m:I
  #20 = Utf8               com/enjoy/learn/core/oop/method/TestClass
  #21 = Utf8               java/lang/Object
{
  public com.enjoy.learn.core.oop.method.TestClass();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 10: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/enjoy/learn/core/oop/method/TestClass;

  public int inc();
    descriptor: ()I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field m:I
         4: iconst_1
         5: iadd
         6: ireturn
      LineNumberTable:
        line 13: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       7     0  this   Lcom/enjoy/learn/core/oop/method/TestClass;
}
SourceFile: "TestClass.java"

1.u4 magic;

ca fe ba be

2.u2 minor_version;

00 00

3.u2 major_version;

00 34
也即版本号为十进制的52

4.u2 constant_pool_count;

00 16
也即十进制的22,由于常量池保留了0项,所以常量池的项目范围是1-21.

5.cp_info constant_pool[constant_pool_count-1];

cp_info {
    u1 tag;
    u1 info[];
}

info的大小根据tag的不同而不同,其中tag的种类如下:


CONSTANT_Utf8_info {
    u1 tag;
    u2 length;
    u1 bytes[length];
}

CONSTANT_Integer_info {
    u1 tag;
    u4 bytes; //高位在前存储的int值
}

CONSTANT_Float_info {
    u1 tag;
    u4 bytes;
}

CONSTANT_Long_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
}

CONSTANT_Double_info {
    u1 tag;
    u4 high_bytes;
    u4 low_bytes;
}

CONSTANT_Class_info {
    u1 tag;
    u2 name_index; //指向常量池的索引,代表类的全限定名Utf8类型常量
}

CONSTANT_String_info {
    u1 tag;
    u2 string_index;
}

CONSTANT_Fieldref_info {
    u1 tag;
    u2 class_index; //类或接口的索引Class_info
    u2 name_and_type_index; //字段描述符的索引
}

CONSTANT_Methodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

CONSTANT_InterfaceMethodref_info {
    u1 tag;
    u2 class_index;
    u2 name_and_type_index;
}

CONSTANT_NameAndType_info {
    u1 tag;
    u2 name_index;
    u2 descriptor_index;
}

CONSTANT_MethodHandle_info {
    u1 tag;
    u1 reference_kind;
    u2 reference_index;
}

CONSTANT_MethodType_info {
    u1 tag;
    u2 descriptor_index;
}

CONSTANT_InvokeDynamic_info {
    u1 tag;
    u2 bootstrap_method_attr_index;
    u2 name_and_type_index;
}

阅读class文件:
1)0a 代表Methodref,后面u2 class_index; u2 name_and_type_index;
00 04 java/lang/Object
00 12 (十进制18)<init> ()V
2)09 代表Fieldref,后面u2 class_index; u2 name_and_type_index;
00 03 com/enjoy/learn/core/oop/method/TestClass
00 13 (十进制19)m I
3)07代表Class,后面u2 name_index
00 14 (十进制20)com/enjoy/learn/core/oop/method/TestClass
4)07代表Class,后面u2 name_index
00 15(十进制21)
java/lang/Object
5)01代表utf8, u2 length; u1 bytes[length];
00 01表示长度为1
6d m
6)01代表utf8, u2 length; u1 bytes[length];
00 01表示长度为1
49 I
7)01代表utf8, u2 length; u1 bytes[length];
00 06长度为6
3c 69 6e 69 74 3e <init>
8)01代表utf8, u2 length; u1 bytes[length];
00 03长度为3
28 29 56 ()V
9)01代表utf8, u2 length; u1 bytes[length];
00 04长度为4
43 6f 64 65 Code
10)01代表utf8, u2 length; u1 bytes[length];
00 0f长度为15
4c 69 6e 65 4e 75 6d 62
65 72 54 61 62 6c 65 LineNumberTable
11)01代表utf8, u2 length; u1 bytes[length];
00 12长度为18
4c 6f 63 61 6c 56 61 72
69 61 62 6c 65 54 61 62
6c 65 LocalVariableTable
12)01代表utf8, u2 length; u1 bytes[length];
00 04长度为4
74 68 69 73 this
13)01代表utf8, u2 length; u1 bytes[length];
00 2b长度为43
4c 63 6f 6d 2f 65 6e
6a 6f 79 2f 6c 65 61 72 6e 2f 63 6f 72 65 2f 6f
6f 70 2f 6d 65 74 68 6f 64 2f 54 65 73 74 43 6c
61 73 73 3b Lcom/enjoy/learn/core/oop/method/TestClass
14)01代表utf8, u2 length; u1 bytes[length];
00 03长度为3
69 6e 63 代表 inc
15)01代表utf8, u2 length; u1 bytes[length];
00 03长度为3
28 29 49 代表 ()I
16)01代表utf8, u2 length; u1 bytes[length];
00 0a长度为10
53 6f 75 72 63 65 46 69 6c 65 SourceFile
17)01代表utf8, u2 length; u1 bytes[length];
00 0e长度为14
54 65 73 74 43 6c 61 73 73 2e 6a 61 76 61 TestClass.java
18)0c代表NameAndType, u2 name_index;u2 descriptor_index;
00 07 <init>
00 08 ()V
19)0c代表NameAndType, u2 name_index;u2 descriptor_index;
00 05 m
00 06 I
20)01代表utf8, u2 length; u1 bytes[length];
00 29长度为41
63 6f 6d 2f 65
6e 6a 6f 79 2f 6c 65 61 72 6e 2f 63 6f 72 65 2f
6f 6f 70 2f 6d 65 74 68 6f 64 2f 54 65 73 74 43
6c 61 73 73 com/enjoy/learn/core/oop/method/TestClass
21)01代表utf8, u2 length; u1 bytes[length];
00 10长度为16
6a 61 76 61 2f 6c 61 6e 67
2f 4f 62 6a 65 63 74 java/lang/Object

javap -v 翻译过后

Constant pool:
   #1 = Methodref          #4.#18         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#19         // com/enjoy/learn/core/oop/method/TestClass.m:I
   #3 = Class              #20            // com/enjoy/learn/core/oop/method/TestClass
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               m
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/enjoy/learn/core/oop/method/TestClass;
  #14 = Utf8               inc
  #15 = Utf8               ()I
  #16 = Utf8               SourceFile
  #17 = Utf8               TestClass.java
  #18 = NameAndType        #7:#8          // "<init>":()V
  #19 = NameAndType        #5:#6          // m:I
  #20 = Utf8               com/enjoy/learn/core/oop/method/TestClass
  #21 = Utf8               java/lang/Object

6.u2 access_flags;

00 21
表示ACC_PUBLIC ACC_SUPER


flags: (0x0021) ACC_PUBLIC, ACC_SUPER

7.u2 this_class;

00 03 常量池 #3 = Class #20 // com/enjoy/learn/core/oop/method/TestClass
类索引用于确定该类的全限定名

this_class: #3                          // com/enjoy/learn/core/oop/method/TestClass

8.u2 super_class;

00 04 常量池#4 = Class #21 // java/lang/Object
确定父类的全限定名

super_class: #4                         // java/lang/Object

9.u2 interfaces_count;

00 00 表示该类没有实现任何接口

10.u2 interfaces[interfaces_count];

确定该类实现了哪些接口

interfaces: 0

11.u2 fields_count;

00 01

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]; 
}

00 02 access_flags
表示private


00 05 name_index (常量池索引)字段的简单名称
查看#5 = Utf8 m

00 06 descriptor_index (常量池索引)字段描述符
查看 #6 = Utf8 I

00 00 attributes_count
如果声明改为"final static int m = 123;",则有一个ConstantValue属性,其值指向常量123.

由上可知字段定义为:private int m;

注意事项:
1)不会出现超类或父类中继承而来的字段
2)可能会列出原本不存在的字段:例如内部类对外部类的访问

13.u2 methods_count;

00 02 有两个方法

14.method_info methods[methods_count];

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

00 01 access_flags
ACC_PUBLIC


00 07 name_index
代表 #7 = Utf8 <init>

00 08 descriptor_index
代表 #8 = Utf8 ()V

00 01 attributes_count 有一个属性

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

00 09 attribute_name_index
代表#9 = Utf8 Code
代表此属性是方法的字节码描述
00 00 00 2f attribute_length(长度为47)

Code属性表:

Code_attribute {
    u2 attribute_name_index;  //复用上面的
    u4 attribute_length; //复用上面的
    u2 max_stack;
    u2 max_locals;
    u4 code_length;
    u1 code[code_length];
    u2 exception_table_length;
    {   u2 start_pc;
        u2 end_pc;
        u2 handler_pc;
        u2 catch_type;
    } exception_table[exception_table_length];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

00 01 max_stack
00 01 max_locals

00 00 00 05 code_length
2a //aload_0 将第0个引用类型本地变量推送至栈顶
b7 // invokespecial 以栈顶的引用类型的对象作为方法接收者,调用此对象的实例构造方法、private方法或者其父类方法。该方法有一个u2类型参数,指向常量池中的CONSTANT_Methodref_info常量,即方法的符号引用。
00 01 //方法的符号引用#1 = Methodref #4.#18 // java/lang/Object."<init>":()V
b1 //return 从当前方法返回void

00 00 exception_table_length
exception_table[exception_table_length]为空

00 02 attributes_count 两个大小
00 0a attribute_name_index //#10 = Utf8 LineNumberTable
00 00 00 06 attribute_length
00 01 line_number_table_length
00 00 start_pc
00 0a line_number

LineNumberTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 line_number_table_length;
    {   u2 start_pc;
        u2 line_number; 
    } line_number_table[line_number_table_length];
}

00 0b attribute_name_index//#11 = Utf8 LocalVariableTable
00 00 00 0c attribute_length
00 01 local_variable_table_length
00 00 start_pc
00 05 length
00 0c name_index ——> this
00 0d descriptor_index ——> #13 = Utf8 Lcom/enjoy/learn/core/oop/method/TestClass;
00 00 index

LocalVariableTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 local_variable_table_length;
    {   u2 start_pc;
        u2 length;
        u2 name_index;
        u2 descriptor_index;
        u2 index;
    } local_variable_table[local_variable_table_length];
}
  public com.enjoy.learn.core.oop.method.TestClass();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 10: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/enjoy/learn/core/oop/method/TestClass;

如下为第二个方法:

00 01 access_flags
ACC_PUBLIC

00 0e name_index
代表#14 = Utf8 inc

00 0f descriptor_index
代表#15 = Utf8 ()I

00 01 attributes_count

00 09 attribute_name_index
代表#9 = Utf8 Code
代表此属性是方法的字节码描述

00 00 00 31 attribute_length

  public int inc();
    descriptor: ()I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field m:I
         4: iconst_1
         5: iadd
         6: ireturn
      LineNumberTable:
        line 13: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       7     0  this   Lcom/enjoy/learn/core/oop/method/TestClass;

注意:
1)如果方法未被重写,父类方法不会出现
2)可能会出现由编译器自动添加的方法:类构造器<cinit>和实例构造器<init>
3)任何实例方法中,都可以通过this关键字访问到此方法所属的对象。实例方法的局部变量表中至少会存在this,第一个Slot位置给this,方法参数值从1开始。static方法从0开始。

15.u2 attributes_count;

00 01

16.attribute_info attributes[attributes_count];

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

00 10 attribute_name_index
代表 #16 = Utf8 SourceFile
00 00 00 02 attribute_length
00 11
代表 #17 = Utf8 TestClass.java

SourceFile: "TestClass.java"

属性表出现在:
1)Class文件
RuntimeVisibleTypeAnnotations
RuntimeInviisibleTypeAnnotations —— 三者+Code属性均可用
Deprecated——三者均可用
Signature——三者均可用 记录泛型签名信息,为了避免擦除后信息丢失
Synthetic —— 三者均可 编译器自动生成
RuntimeVisibleAnnotations—— 三者均可用 运行时可见,反射调用
RuntimeInvisivleAnnotations——运行时不可见

EnclosingMethod——局部类或匿名类的外围方法
InnerClasses——内部类列表
SourceFile——源文件名称
SourceDebugExtension——存储额外的调试信息
BootstrapMethods——用于保存invokedynamic指令引用的引导方法限定符

2)字段表
ConstantValue——final字段

3)方法表
Code——字节码指令
 LineNumberTable——Code属性 源码行号
 LocalVariableTable——Code属性 局部变量
 LocalVariableTypeTable——使用特征签名代替描述符,描述泛型 参数化类型
 StackMapTable——局部变量和操作数栈所需类型是否匹配
Exceptions——方法抛出的异常
RuntimeVisibleParameterAnnotations——方法参数注解
RuntimeInvisibleParameterAnnotations——方法参数注解
AnnotationDefault——默认值
MethodParameters——


按照新增属性的前后顺序:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343