# 一. class 文件介绍

# 1.什么是 class 文件

Java 源代码经过编译器编译后产生的二进制文件称为 Java 类文件。这些类文件包含了与 Java 源代码对应的字节码,而字节码是一种中间代码,介于源代码和机器码之间。Java 类文件通常具有.class的扩展名。

当你编写 Java 程序时,你首先使用文本编辑器(如 Java 的开发工具,如 Eclipse、IntelliJ IDEA 等)编写源代码文件(扩展名为.java)。然后,你使用 Java 编译器(javac命令)将源代码编译成字节码,生成对应的 Java 类文件。最后,Java 虚拟机(JVM)会执行这些类文件中的字节码。

Java 类文件包含了类的结构信息、字段、方法以及其他一些与类相关的信息。这种中间表示形式使得 Java 具有平台无关性,因为一旦生成了字节码,它就可以在任何支持 Java 虚拟机的平台上运行,而无需重新编译。

# 2.类文件的结构

类文件的结构是由 Java 虚拟机规范定义的,包括魔数、版本信息、常量池、访问标志、类信息、字段信息、方法信息等部分。虽然类文件可以通过反编译工具(如javap、JD-GUI 等)进行查看和分析,但是这些工具仅提供了类的结构信息,而不包括原始的源代码。

总的来说,Java 类文件是 Java 程序的编译结果,其中包含了以字节码形式表示的程序的中间表示。这种设计使得 Java 能够实现跨平台的特性,因为字节码可以在任何支持 Java 虚拟机的计算机上运行。

# 3.如何查看 class 文件

要查看 Java 类文件的内容,可以使用多种工具。其中最常用的工具之一是javap命令,它是 Java Development Kit(JDK)中的一部分。以下是一些使用javap的基本示例:

  1. 使用 javap 查看类的成员变量和方法:

    javap YourClassName
    
    1

    例如,如果你有一个名为MyClass的类文件,可以运行以下命令:

    javap MyClass
    
    1

    这将显示类的成员变量和方法的信息。

  2. 使用 javap 查看详细信息:

    javap -verbose YourClassName
    
    1

    这将显示更详细的类信息,包括常量池、字段描述符、方法描述符等。

  3. 将输出保存到文件:

    javap -verbose YourClassName > output.txt
    
    1

    这将把javap的输出保存到一个名为output.txt的文件中,以便在文本编辑器中查看。

确保在运行这些命令之前,你已经安装了 Java Development Kit(JDK)并设置了相应的环境变量。如果你在命令行中运行这些命令时遇到问题,可能需要检查你的 Java 安装是否正确。

请注意,通过反编译工具查看类文件可能违反软件使用条款或法律规定,因此请确保你有权利查看和使用这些文件。

# 4.文章背景

之前也看过深入理解java虚拟机这本书,里面详细介绍了 class 文件的结构,自己也能说出来一些,但是仅限于八股文的地步,并没有了解书中每个 class 文件结构在实际代码中的含义,不能做到举一反三,完全停留在背八股的阶段。

通过本文详细的对 class 文件分析,结合深入理解java虚拟机这本书,可以更深刻的理解 class 文件结构,而不是停留在死记硬背的阶段。

# 二.数据准备

# 1.实体类

@Data
@ApiModel("chatgpt问答实体类")
public class Student extends Model<Student> implements Serializable {
    private static final long serialVersionUID = 1L;

    private static final String name = "qinyingjie1";

    private static String notFinal = "qinyingjie2";

    private final String nameNoStatic = "qinyingjie_nameNoStatic";

    private  String noneName = "qinyingjie_noneName";

    private static final Integer num = 20;

    private static final int intnum = 30;

    private static final String newStr = new String("qinyuchen");

    @ApiModelProperty("主键id")
    private Integer id;
    @ApiModelProperty("问题")
    private String question;
    @ApiModelProperty("回答")
    private String response;
    @ApiModelProperty("创建时间")
    private Date createTime;
    @ApiModelProperty("删除标识")
    private Integer isDelete;

    public static String getStr() {
        return "qyj";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 2.Class 文件

@ApiModel("chatgpt问答实体类")
public class Student extends Model<Student> implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final String name = "qinyingjie1";
    private static String notFinal = "qinyingjie2";
    private final String nameNoStatic = "qinyingjie_nameNoStatic";
    private String noneName = "qinyingjie_noneName";
    private static final Integer num = 20;
    private static final int intnum = 30;
    private static final String newStr = new String("qinyuchen");
    @ApiModelProperty("主键id")
    private Integer id;
    @ApiModelProperty("问题")
    private String question;
    @ApiModelProperty("回答")
    private String response;
    @ApiModelProperty("创建时间")
    private Date createTime;
    @ApiModelProperty("删除标识")
    private Integer isDelete;

    public static String getStr() {
        return "qyj";
    }

    public Student() {
    }

    public String getNameNoStatic() {
        this.getClass();
        return "qinyingjie_nameNoStatic";
    }

    public String getNoneName() {
        return this.noneName;
    }

    public Integer getId() {
        return this.id;
    }

    public String getQuestion() {
        return this.question;
    }

    public String getResponse() {
        return this.response;
    }

    public Date getCreateTime() {
        return this.createTime;
    }

    public Integer getIsDelete() {
        return this.isDelete;
    }

    public void setNoneName(final String noneName) {
        this.noneName = noneName;
    }

    public void setId(final Integer id) {
        this.id = id;
    }

    public void setQuestion(final String question) {
        this.question = question;
    }

    public void setResponse(final String response) {
        this.response = response;
    }

    public void setCreateTime(final Date createTime) {
        this.createTime = createTime;
    }

    public void setIsDelete(final Integer isDelete) {
        this.isDelete = isDelete;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Student)) {
            return false;
        } else {
            Student other = (Student)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label95: {
                    Object this$id = this.getId();
                    Object other$id = other.getId();
                    if (this$id == null) {
                        if (other$id == null) {
                            break label95;
                        }
                    } else if (this$id.equals(other$id)) {
                        break label95;
                    }

                    return false;
                }

                Object this$isDelete = this.getIsDelete();
                Object other$isDelete = other.getIsDelete();
                if (this$isDelete == null) {
                    if (other$isDelete != null) {
                        return false;
                    }
                } else if (!this$isDelete.equals(other$isDelete)) {
                    return false;
                }

                Object this$nameNoStatic = this.getNameNoStatic();
                Object other$nameNoStatic = other.getNameNoStatic();
                if (this$nameNoStatic == null) {
                    if (other$nameNoStatic != null) {
                        return false;
                    }
                } else if (!this$nameNoStatic.equals(other$nameNoStatic)) {
                    return false;
                }

                label74: {
                    Object this$noneName = this.getNoneName();
                    Object other$noneName = other.getNoneName();
                    if (this$noneName == null) {
                        if (other$noneName == null) {
                            break label74;
                        }
                    } else if (this$noneName.equals(other$noneName)) {
                        break label74;
                    }

                    return false;
                }

                label67: {
                    Object this$question = this.getQuestion();
                    Object other$question = other.getQuestion();
                    if (this$question == null) {
                        if (other$question == null) {
                            break label67;
                        }
                    } else if (this$question.equals(other$question)) {
                        break label67;
                    }

                    return false;
                }

                Object this$response = this.getResponse();
                Object other$response = other.getResponse();
                if (this$response == null) {
                    if (other$response != null) {
                        return false;
                    }
                } else if (!this$response.equals(other$response)) {
                    return false;
                }

                Object this$createTime = this.getCreateTime();
                Object other$createTime = other.getCreateTime();
                if (this$createTime == null) {
                    if (other$createTime != null) {
                        return false;
                    }
                } else if (!this$createTime.equals(other$createTime)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof Student;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.getId();
        int result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $isDelete = this.getIsDelete();
        result = result * 59 + ($isDelete == null ? 43 : $isDelete.hashCode());
        Object $nameNoStatic = this.getNameNoStatic();
        result = result * 59 + ($nameNoStatic == null ? 43 : $nameNoStatic.hashCode());
        Object $noneName = this.getNoneName();
        result = result * 59 + ($noneName == null ? 43 : $noneName.hashCode());
        Object $question = this.getQuestion();
        result = result * 59 + ($question == null ? 43 : $question.hashCode());
        Object $response = this.getResponse();
        result = result * 59 + ($response == null ? 43 : $response.hashCode());
        Object $createTime = this.getCreateTime();
        result = result * 59 + ($createTime == null ? 43 : $createTime.hashCode());
        return result;
    }

    public String toString() {
        return "Student(nameNoStatic=" + this.getNameNoStatic() + ", noneName=" + this.getNoneName() + ", id=" + this.getId() + ", question=" + this.getQuestion() + ", response=" + this.getResponse() + ", createTime=" + this.getCreateTime() + ", isDelete=" + this.getIsDelete() + ")";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

# 3.查看 class 文件

#查看class文件的详细信息
javap -verbose Student
1
2

Student的Class文件详细信息如下所示,下面进行逐行分析

警告: 二进制文件Student包含com.kwan.springbootkwan.entity.Student
Classfile /Users/qinyingjie/Documents/idea-workspace/vue-springboot-kwan/target/classes/com/kwan/springbootkwan/entity/Student.class
  Last modified 2023-12-2; size 5396 bytes
  MD5 checksum 9424b6c0d7363472a517799b5f5191b5
  Compiled from "Student.java"
public class com.kwan.springbootkwan.entity.Student extends com.baomidou.mybatisplus.extension.activerecord.Model<com.kwan.springbootkwan.entity.Student> implements java.io.Serializable
  minor version: 0
  major version: 52
  flags: ACC_PUBLICACC_SUPER
Constant pool:
    #1 = String             #148          // qyj  静态方法中的字符串
    #2 = Methodref          #45.#149      // com/baomidou/mybatisplus/extension/activerecord/Model."<init>":()V
    #3 = String             #150          // qinyingjie_nameNoStatic
    #4 = Fieldref           #13.#151      // com/kwan/springbootkwan/entity/Student.nameNoStatic:Ljava/lang/String;
    #5 = String             #152          // qinyingjie_noneName
    #6 = Fieldref           #13.#153      // com/kwan/springbootkwan/entity/Student.noneName:Ljava/lang/String;
    #7 = Methodref          #154.#155     // java/lang/Object.getClass:()Ljava/lang/Class;
    #8 = Fieldref           #13.#156      // com/kwan/springbootkwan/entity/Student.id:Ljava/lang/Integer;
    #9 = Fieldref           #13.#157      // com/kwan/springbootkwan/entity/Student.question:Ljava/lang/String;
   #10 = Fieldref           #13.#158      // com/kwan/springbootkwan/entity/Student.response:Ljava/lang/String;
   #11 = Fieldref           #13.#159      // com/kwan/springbootkwan/entity/Student.createTime:Ljava/util/Date;
   #12 = Fieldref           #13.#160      // com/kwan/springbootkwan/entity/Student.isDelete:Ljava/lang/Integer;
   #13 = Class              #161          // com/kwan/springbootkwan/entity/Student
   #14 = Methodref          #13.#162      // com/kwan/springbootkwan/entity/Student.canEqual:(Ljava/lang/Object;)Z
   #15 = Methodref          #13.#163      // com/kwan/springbootkwan/entity/Student.getId:()Ljava/lang/Integer;
   #16 = Methodref          #154.#164     // java/lang/Object.equals:(Ljava/lang/Object;)Z
   #17 = Methodref          #13.#165      // com/kwan/springbootkwan/entity/Student.getIsDelete:()Ljava/lang/Integer;
   #18 = Methodref          #13.#166      // com/kwan/springbootkwan/entity/Student.getNameNoStatic:()Ljava/lang/String;
   #19 = Methodref          #13.#167      // com/kwan/springbootkwan/entity/Student.getNoneName:()Ljava/lang/String;
   #20 = Methodref          #13.#168      // com/kwan/springbootkwan/entity/Student.getQuestion:()Ljava/lang/String;
   #21 = Methodref          #13.#169      // com/kwan/springbootkwan/entity/Student.getResponse:()Ljava/lang/String;
   #22 = Methodref          #13.#170      // com/kwan/springbootkwan/entity/Student.getCreateTime:()Ljava/util/Date;
   #23 = Methodref          #154.#171     // java/lang/Object.hashCode:()I
   #24 = Class              #172          // java/lang/StringBuilder
   #25 = Methodref          #24.#149      // java/lang/StringBuilder."<init>":()V
   #26 = String             #173          // Student(nameNoStatic=
   #27 = Methodref          #24.#174      // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #28 = String             #175          // , noneName=
   #29 = String             #176          // , id=
   #30 = Methodref          #24.#177      // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
   #31 = String             #178          // , question=
   #32 = String             #179          // , response=
   #33 = String             #180          // , createTime=
   #34 = String             #181          // , isDelete=
   #35 = String             #182          // )
   #36 = Methodref          #24.#183      // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #37 = String             #184          // qinyingjie2
   #38 = Fieldref           #13.#185      // com/kwan/springbootkwan/entity/Student.notFinal:Ljava/lang/String;
   #39 = Methodref          #186.#187     // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #40 = Fieldref           #13.#188      // com/kwan/springbootkwan/entity/Student.num:Ljava/lang/Integer;
   #41 = Class              #189          // java/lang/String
   #42 = String             #190          // qinyuchen
   #43 = Methodref          #41.#191      // java/lang/String."<init>":(Ljava/lang/String;)V
   #44 = Fieldref           #13.#192      // com/kwan/springbootkwan/entity/Student.newStr:Ljava/lang/String;
   #45 = Class              #193          // com/baomidou/mybatisplus/extension/activerecord/Model
   #46 = Class              #194          // java/io/Serializable
   #47 = Utf8               serialVersionUID
   #48 = Utf8               J
   #49 = Utf8               ConstantValue
   #50 = Long               1l
   #52 = Utf8               name
   #53 = Utf8               Ljava/lang/String;
   #54 = String             #195          // qinyingjie1
   #55 = Utf8               notFinal
   #56 = Utf8               nameNoStatic
   #57 = Utf8               noneName
   #58 = Utf8               num
   #59 = Utf8               Ljava/lang/Integer;
   #60 = Utf8               intnum
   #61 = Utf8               I
   #62 = Integer            30
   #63 = Utf8               newStr
   #64 = Utf8               id
   #65 = Utf8               RuntimeVisibleAnnotations
   #66 = Utf8               Lio/swagger/annotations/ApiModelProperty;
   #67 = Utf8               value
   #68 = Utf8               主键id
   #69 = Utf8               question
   #70 = Utf8               问题
   #71 = Utf8               response
   #72 = Utf8               回答
   #73 = Utf8               createTime
   #74 = Utf8               Ljava/util/Date;
   #75 = Utf8               创建时间
   #76 = Utf8               isDelete
   #77 = Utf8               删除标识
   #78 = Utf8               getStr
   #79 = Utf8               ()Ljava/lang/String;
   #80 = Utf8               Code
   #81 = Utf8               LineNumberTable
   #82 = Utf8               <init>
   #83 = Utf8               ()V
   #84 = Utf8               LocalVariableTable
   #85 = Utf8               this
   #86 = Utf8               Lcom/kwan/springbootkwan/entity/Student;
   #87 = Utf8               getNameNoStatic
   #88 = Utf8               getNoneName
   #89 = Utf8               getId
   #90 = Utf8               ()Ljava/lang/Integer;
   #91 = Utf8               getQuestion
   #92 = Utf8               getResponse
   #93 = Utf8               getCreateTime
   #94 = Utf8               ()Ljava/util/Date;
   #95 = Utf8               getIsDelete
   #96 = Utf8               setNoneName
   #97 = Utf8               (Ljava/lang/String;)V
   #98 = Utf8               MethodParameters
   #99 = Utf8               setId
  #100 = Utf8               (Ljava/lang/Integer;)V
  #101 = Utf8               setQuestion
  #102 = Utf8               setResponse
  #103 = Utf8               setCreateTime
  #104 = Utf8               (Ljava/util/Date;)V
  #105 = Utf8               setIsDelete
  #106 = Utf8               equals
  #107 = Utf8               (Ljava/lang/Object;)Z
  #108 = Utf8               o
  #109 = Utf8               Ljava/lang/Object;
  #110 = Utf8               other
  #111 = Utf8               this$id
  #112 = Utf8               other$id
  #113 = Utf8               this$isDelete
  #114 = Utf8               other$isDelete
  #115 = Utf8               this$nameNoStatic
  #116 = Utf8               other$nameNoStatic
  #117 = Utf8               this$noneName
  #118 = Utf8               other$noneName
  #119 = Utf8               this$question
  #120 = Utf8               other$question
  #121 = Utf8               this$response
  #122 = Utf8               other$response
  #123 = Utf8               this$createTime
  #124 = Utf8               other$createTime
  #125 = Utf8               StackMapTable
  #126 = Class              #161          // com/kwan/springbootkwan/entity/Student
  #127 = Class              #196          // java/lang/Object
  #128 = Utf8               canEqual
  #129 = Utf8               hashCode
  #130 = Utf8               ()I
  #131 = Utf8               PRIME
  #132 = Utf8               result
  #133 = Utf8               $id
  #134 = Utf8               $isDelete
  #135 = Utf8               $nameNoStatic
  #136 = Utf8               $noneName
  #137 = Utf8               $question
  #138 = Utf8               $response
  #139 = Utf8               $createTime
  #140 = Utf8               toString
  #141 = Utf8               <clinit>
  #142 = Utf8               Signature
  #143 = Utf8               Lcom/baomidou/mybatisplus/extension/activerecord/Model<Lcom/kwan/springbootkwan/entity/Student;>;Ljava/io/Serializable;
  #144 = Utf8               SourceFile
  #145 = Utf8               Student.java
  #146 = Utf8               Lio/swagger/annotations/ApiModel;
  #147 = Utf8               chatgpt问答实体类
  #148 = Utf8               qyj
  #149 = NameAndType        #82:#83       // "<init>":()V
  #150 = Utf8               qinyingjie_nameNoStatic
  #151 = NameAndType        #56:#53       // nameNoStatic:Ljava/lang/String;
  #152 = Utf8               qinyingjie_noneName
  #153 = NameAndType        #57:#53       // noneName:Ljava/lang/String;
  #154 = Class              #196          // java/lang/Object
  #155 = NameAndType        #197:#198     // getClass:()Ljava/lang/Class;
  #156 = NameAndType        #64:#59       // id:Ljava/lang/Integer;
  #157 = NameAndType        #69:#53       // question:Ljava/lang/String;
  #158 = NameAndType        #71:#53       // response:Ljava/lang/String;
  #159 = NameAndType        #73:#74       // createTime:Ljava/util/Date;
  #160 = NameAndType        #76:#59       // isDelete:Ljava/lang/Integer;
  #161 = Utf8               com/kwan/springbootkwan/entity/Student
  #162 = NameAndType        #128:#107     // canEqual:(Ljava/lang/Object;)Z
  #163 = NameAndType        #89:#90       // getId:()Ljava/lang/Integer;
  #164 = NameAndType        #106:#107     // equals:(Ljava/lang/Object;)Z
  #165 = NameAndType        #95:#90       // getIsDelete:()Ljava/lang/Integer;
  #166 = NameAndType        #87:#79       // getNameNoStatic:()Ljava/lang/String;
  #167 = NameAndType        #88:#79       // getNoneName:()Ljava/lang/String;
  #168 = NameAndType        #91:#79       // getQuestion:()Ljava/lang/String;
  #169 = NameAndType        #92:#79       // getResponse:()Ljava/lang/String;
  #170 = NameAndType        #93:#94       // getCreateTime:()Ljava/util/Date;
  #171 = NameAndType        #129:#130     // hashCode:()I
  #172 = Utf8               java/lang/StringBuilder
  #173 = Utf8               Student(nameNoStatic=
  #174 = NameAndType        #199:#200     // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #175 = Utf8               , noneName=
  #176 = Utf8               , id=
  #177 = NameAndType        #199:#201     // append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #178 = Utf8               , question=
  #179 = Utf8               , response=
  #180 = Utf8               , createTime=
  #181 = Utf8               , isDelete=
  #182 = Utf8               )
  #183 = NameAndType        #140:#79      // toString:()Ljava/lang/String;
  #184 = Utf8               qinyingjie2
  #185 = NameAndType        #55:#53       // notFinal:Ljava/lang/String;
  #186 = Class              #202          // java/lang/Integer
  #187 = NameAndType        #203:#204     // valueOf:(I)Ljava/lang/Integer;
  #188 = NameAndType        #58:#59       // num:Ljava/lang/Integer;
  #189 = Utf8               java/lang/String
  #190 = Utf8               qinyuchen
  #191 = NameAndType        #82:#97       // "<init>":(Ljava/lang/String;)V
  #192 = NameAndType        #63:#53       // newStr:Ljava/lang/String;
  #193 = Utf8               com/baomidou/mybatisplus/extension/activerecord/Model
  #194 = Utf8               java/io/Serializable
  #195 = Utf8               qinyingjie1
  #196 = Utf8               java/lang/Object
  #197 = Utf8               getClass
  #198 = Utf8               ()Ljava/lang/Class;
  #199 = Utf8               append
  #200 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #201 = Utf8               (Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #202 = Utf8               java/lang/Integer
  #203 = Utf8               valueOf
  #204 = Utf8               (I)Ljava/lang/Integer;
{
  public static java.lang.String getStr();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLICACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #1                  // String qyj
         2: areturn
      LineNumberTable:
        line 43: 0

  public com.kwan.springbootkwan.entity.Student();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #2                  // Method com/baomidou/mybatisplus/extension/activerecord/Model."<init>":()V
         4: aload_0
         5: ldc           #3                  // String qinyingjie_nameNoStatic
         7: putfield      #4                  // Field nameNoStatic:Ljava/lang/String;
        10: aload_0
        11: ldc           #5                  // String qinyingjie_noneName
        13: putfield      #6                  // Field noneName:Ljava/lang/String;
        16: return
      LineNumberTable:
        line 12: 0
        line 21: 4
        line 23: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      17     0  this   Lcom/kwan/springbootkwan/entity/Student;

  public java.lang.String getNameNoStatic();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokevirtual #7                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
         4: pop
         5: ldc           #3                  // String qinyingjie_nameNoStatic
         7: areturn
      LineNumberTable:
        line 21: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       8     0  this   Lcom/kwan/springbootkwan/entity/Student;

  public java.lang.String getNoneName();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #6                  // Field noneName:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 23: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;

  public java.lang.Integer getId();
    descriptor: ()Ljava/lang/Integer;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #8                  // Field id:Ljava/lang/Integer;
         4: areturn
      LineNumberTable:
        line 32: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;

  public java.lang.String getQuestion();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #9                  // Field question:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 34: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;

  public java.lang.String getResponse();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #10                 // Field response:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 36: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;

  public java.util.Date getCreateTime();
    descriptor: ()Ljava/util/Date;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #11                 // Field createTime:Ljava/util/Date;
         4: areturn
      LineNumberTable:
        line 38: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;

  public java.lang.Integer getIsDelete();
    descriptor: ()Ljava/lang/Integer;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #12                 // Field isDelete:Ljava/lang/Integer;
         4: areturn
      LineNumberTable:
        line 40: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;

  public void setNoneName(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #6                  // Field noneName:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0       6     1 noneName   Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      noneName                       final

  public void setId(java.lang.Integer);
    descriptor: (Ljava/lang/Integer;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #8                  // Field id:Ljava/lang/Integer;
         5: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0       6     1    id   Ljava/lang/Integer;
    MethodParameters:
      Name                           Flags
      id                             final

  public void setQuestion(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #9                  // Field question:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0       6     1 question   Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      question                       final

  public void setResponse(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #10                 // Field response:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0       6     1 response   Ljava/lang/String;
    MethodParameters:
      Name                           Flags
      response                       final

  public void setCreateTime(java.util.Date);
    descriptor: (Ljava/util/Date;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #11                 // Field createTime:Ljava/util/Date;
         5: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0       6     1 createTime   Ljava/util/Date;
    MethodParameters:
      Name                           Flags
      createTime                     final

  public void setIsDelete(java.lang.Integer);
    descriptor: (Ljava/lang/Integer;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #12                 // Field isDelete:Ljava/lang/Integer;
         5: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0       6     1 isDelete   Ljava/lang/Integer;
    MethodParameters:
      Name                           Flags
      isDelete                       final

  public boolean equals(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Z
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=17, args_size=2
         0: aload_1
         1: aload_0
         2: if_acmpne     7
         5: iconst_1
         6: ireturn
         7: aload_1
         8: instanceof    #13                 // class com/kwan/springbootkwan/entity/Student
        11: ifne          16
        14: iconst_0
        15: ireturn
        16: aload_1
        17: checkcast     #13                 // class com/kwan/springbootkwan/entity/Student
        20: astore_2
        21: aload_2
        22: aload_0
        23: invokevirtual #14                 // Method canEqual:(Ljava/lang/Object;)Z
        26: ifne          31
        29: iconst_0
        30: ireturn
        31: aload_0
        32: invokevirtual #15                 // Method getId:()Ljava/lang/Integer;
        35: astore_3
        36: aload_2
        37: invokevirtual #15                 // Method getId:()Ljava/lang/Integer;
        40: astore        4
        42: aload_3
        43: ifnonnull     54
        46: aload         4
        48: ifnull        65
        51: goto          63
        54: aload_3
        55: aload         4
        57: invokevirtual #16                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
        60: ifne          65
        63: iconst_0
        64: ireturn
        65: aload_0
        66: invokevirtual #17                 // Method getIsDelete:()Ljava/lang/Integer;
        69: astore        5
        71: aload_2
        72: invokevirtual #17                 // Method getIsDelete:()Ljava/lang/Integer;
        75: astore        6
        77: aload         5
        79: ifnonnull     90
        82: aload         6
        84: ifnull        102
        87: goto          100
        90: aload         5
        92: aload         6
        94: invokevirtual #16                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
        97: ifne          102
       100: iconst_0
       101: ireturn
       102: aload_0
       103: invokevirtual #18                 // Method getNameNoStatic:()Ljava/lang/String;
       106: astore        7
       108: aload_2
       109: invokevirtual #18                 // Method getNameNoStatic:()Ljava/lang/String;
       112: astore        8
       114: aload         7
       116: ifnonnull     127
       119: aload         8
       121: ifnull        139
       124: goto          137
       127: aload         7
       129: aload         8
       131: invokevirtual #16                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
       134: ifne          139
       137: iconst_0
       138: ireturn
       139: aload_0
       140: invokevirtual #19                 // Method getNoneName:()Ljava/lang/String;
       143: astore        9
       145: aload_2
       146: invokevirtual #19                 // Method getNoneName:()Ljava/lang/String;
       149: astore        10
       151: aload         9
       153: ifnonnull     164
       156: aload         10
       158: ifnull        176
       161: goto          174
       164: aload         9
       166: aload         10
       168: invokevirtual #16                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
       171: ifne          176
       174: iconst_0
       175: ireturn
       176: aload_0
       177: invokevirtual #20                 // Method getQuestion:()Ljava/lang/String;
       180: astore        11
       182: aload_2
       183: invokevirtual #20                 // Method getQuestion:()Ljava/lang/String;
       186: astore        12
       188: aload         11
       190: ifnonnull     201
       193: aload         12
       195: ifnull        213
       198: goto          211
       201: aload         11
       203: aload         12
       205: invokevirtual #16                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
       208: ifne          213
       211: iconst_0
       212: ireturn
       213: aload_0
       214: invokevirtual #21                 // Method getResponse:()Ljava/lang/String;
       217: astore        13
       219: aload_2
       220: invokevirtual #21                 // Method getResponse:()Ljava/lang/String;
       223: astore        14
       225: aload         13
       227: ifnonnull     238
       230: aload         14
       232: ifnull        250
       235: goto          248
       238: aload         13
       240: aload         14
       242: invokevirtual #16                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
       245: ifne          250
       248: iconst_0
       249: ireturn
       250: aload_0
       251: invokevirtual #22                 // Method getCreateTime:()Ljava/util/Date;
       254: astore        15
       256: aload_2
       257: invokevirtual #22                 // Method getCreateTime:()Ljava/util/Date;
       260: astore        16
       262: aload         15
       264: ifnonnull     275
       267: aload         16
       269: ifnull        287
       272: goto          285
       275: aload         15
       277: aload         16
       279: invokevirtual #16                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
       282: ifne          287
       285: iconst_0
       286: ireturn
       287: iconst_1
       288: ireturn
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0     289     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0     289     1     o   Ljava/lang/Object;
           21     268     2 other   Lcom/kwan/springbootkwan/entity/Student;
           36     253     3 this$id   Ljava/lang/Object;
           42     247     4 other$id   Ljava/lang/Object;
           71     218     5 this$isDelete   Ljava/lang/Object;
           77     212     6 other$isDelete   Ljava/lang/Object;
          108     181     7 this$nameNoStatic   Ljava/lang/Object;
          114     175     8 other$nameNoStatic   Ljava/lang/Object;
          145     144     9 this$noneName   Ljava/lang/Object;
          151     138    10 other$noneName   Ljava/lang/Object;
          182     107    11 this$question   Ljava/lang/Object;
          188     101    12 other$question   Ljava/lang/Object;
          219      70    13 this$response   Ljava/lang/Object;
          225      64    14 other$response   Ljava/lang/Object;
          256      33    15 this$createTime   Ljava/lang/Object;
          262      27    16 other$createTime   Ljava/lang/Object;
      StackMapTable: number_of_entries = 24
        frame_type = 7 /* same */
        frame_type = 8 /* same */
        frame_type = 252 /* append */
          offset_delta = 14
          locals = [ class com/kwan/springbootkwan/entity/Student ]
        frame_type = 253 /* append */
          offset_delta = 22
          locals = [ class java/lang/Objectclass java/lang/Object ]
        frame_type = 8 /* same */
        frame_type = 1 /* same */
        frame_type = 253 /* append */
          offset_delta = 24
          locals = [ class java/lang/Objectclass java/lang/Object ]
        frame_type = 9 /* same */
        frame_type = 1 /* same */
        frame_type = 253 /* append */
          offset_delta = 24
          locals = [ class java/lang/Objectclass java/lang/Object ]
        frame_type = 9 /* same */
        frame_type = 1 /* same */
        frame_type = 253 /* append */
          offset_delta = 24
          locals = [ class java/lang/Objectclass java/lang/Object ]
        frame_type = 9 /* same */
        frame_type = 1 /* same */
        frame_type = 253 /* append */
          offset_delta = 24
          locals = [ class java/lang/Objectclass java/lang/Object ]
        frame_type = 9 /* same */
        frame_type = 1 /* same */
        frame_type = 253 /* append */
          offset_delta = 24
          locals = [ class java/lang/Objectclass java/lang/Object ]
        frame_type = 9 /* same */
        frame_type = 1 /* same */
        frame_type = 253 /* append */
          offset_delta = 24
          locals = [ class java/lang/Objectclass java/lang/Object ]
        frame_type = 9 /* same */
        frame_type = 1 /* same */
    MethodParameters:
      Name                           Flags
      o                              final

  protected boolean canEqual(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Z
    flags: ACC_PROTECTED
    Code:
      stack=1, locals=2, args_size=2
         0: aload_1
         1: instanceof    #13                 // class com/kwan/springbootkwan/entity/Student
         4: ireturn
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0       5     1 other   Ljava/lang/Object;
    MethodParameters:
      Name                           Flags
      other                          final

  public int hashCode();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=10, args_size=1
         0: bipush        59
         2: istore_1
         3: iconst_1
         4: istore_2
         5: aload_0
         6: invokevirtual #15                 // Method getId:()Ljava/lang/Integer;
         9: astore_3
        10: iload_2
        11: bipush        59
        13: imul
        14: aload_3
        15: ifnonnull     23
        18: bipush        43
        20: goto          27
        23: aload_3
        24: invokevirtual #23                 // Method java/lang/Object.hashCode:()I
        27: iadd
        28: istore_2
        29: aload_0
        30: invokevirtual #17                 // Method getIsDelete:()Ljava/lang/Integer;
        33: astore        4
        35: iload_2
        36: bipush        59
        38: imul
        39: aload         4
        41: ifnonnull     49
        44: bipush        43
        46: goto          54
        49: aload         4
        51: invokevirtual #23                 // Method java/lang/Object.hashCode:()I
        54: iadd
        55: istore_2
        56: aload_0
        57: invokevirtual #18                 // Method getNameNoStatic:()Ljava/lang/String;
        60: astore        5
        62: iload_2
        63: bipush        59
        65: imul
        66: aload         5
        68: ifnonnull     76
        71: bipush        43
        73: goto          81
        76: aload         5
        78: invokevirtual #23                 // Method java/lang/Object.hashCode:()I
        81: iadd
        82: istore_2
        83: aload_0
        84: invokevirtual #19                 // Method getNoneName:()Ljava/lang/String;
        87: astore        6
        89: iload_2
        90: bipush        59
        92: imul
        93: aload         6
        95: ifnonnull     103
        98: bipush        43
       100: goto          108
       103: aload         6
       105: invokevirtual #23                 // Method java/lang/Object.hashCode:()I
       108: iadd
       109: istore_2
       110: aload_0
       111: invokevirtual #20                 // Method getQuestion:()Ljava/lang/String;
       114: astore        7
       116: iload_2
       117: bipush        59
       119: imul
       120: aload         7
       122: ifnonnull     130
       125: bipush        43
       127: goto          135
       130: aload         7
       132: invokevirtual #23                 // Method java/lang/Object.hashCode:()I
       135: iadd
       136: istore_2
       137: aload_0
       138: invokevirtual #21                 // Method getResponse:()Ljava/lang/String;
       141: astore        8
       143: iload_2
       144: bipush        59
       146: imul
       147: aload         8
       149: ifnonnull     157
       152: bipush        43
       154: goto          162
       157: aload         8
       159: invokevirtual #23                 // Method java/lang/Object.hashCode:()I
       162: iadd
       163: istore_2
       164: aload_0
       165: invokevirtual #22                 // Method getCreateTime:()Ljava/util/Date;
       168: astore        9
       170: iload_2
       171: bipush        59
       173: imul
       174: aload         9
       176: ifnonnull     184
       179: bipush        43
       181: goto          189
       184: aload         9
       186: invokevirtual #23                 // Method java/lang/Object.hashCode:()I
       189: iadd
       190: istore_2
       191: iload_2
       192: ireturn
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0     193     0  this   Lcom/kwan/springbootkwan/entity/Student;
            3     190     1 PRIME   I
            5     188     2 result   I
           10     183     3   $id   Ljava/lang/Object;
           35     158     4 $isDelete   Ljava/lang/Object;
           62     131     5 $nameNoStatic   Ljava/lang/Object;
           89     104     6 $noneName   Ljava/lang/Object;
          116      77     7 $question   Ljava/lang/Object;
          143      50     8 $response   Ljava/lang/Object;
          170      23     9 $createTime   Ljava/lang/Object;
      StackMapTable: number_of_entries = 14
        frame_type = 255 /* full_frame */
          offset_delta = 23
          locals = [ class com/kwan/springbootkwan/entity/Studentintintclass java/lang/Object ]
          stack = [ int ]
        frame_type = 255 /* full_frame */
          offset_delta = 3
          locals = [ class com/kwan/springbootkwan/entity/Studentintintclass java/lang/Object ]
          stack = [ intint ]
        frame_type = 255 /* full_frame */
          offset_delta = 21
          locals = [ class com/kwan/springbootkwan/entity/Studentintintclass java/lang/Objectclass java/lang/Object ]
          stack = [ int ]
        frame_type = 255 /* full_frame */
          offset_delta = 4
          locals = [ class com/kwan/springbootkwan/entity/Studentintintclass java/lang/Objectclass java/lang/Object ]
          stack = [ intint ]
        frame_type = 255 /* full_frame */
          offset_delta = 21
          locals = [ class com/kwan/springbootkwan/entity/Studentintintclass java/lang/Objectclass java/lang/Objectclass java/lang/Object ]
          stack = [ int ]
        frame_type = 255 /* full_frame */
          offset_delta = 4
          locals = [ class com/kwan/springbootkwan/entity/Studentintintclass java/lang/Objectclass java/lang/Objectclass java/lang/Object ]
          stack = [ intint ]
        frame_type = 255 /* full_frame */
          offset_delta = 21
          locals = [ class com/kwan/springbootkwan/entity/Studentintintclass java/lang/Objectclass java/lang/Objectclass java/lang/Objectclass java/lang/Object ]
          stack = [ int ]
        frame_type = 255 /* full_frame */
          offset_delta = 4
          locals = [ class com/kwan/springbootkwan/entity/Studentintintclass java/lang/Objectclass java/lang/Object, class java/lang/Object, class java/lang/Object ]
          stack = [ int, int ]
        frame_type = 255 /* full_frame */
          offset_delta = 21
          locals = [ class com/kwan/springbootkwan/entity/Student, int, int, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object ]
          stack = [ int ]
        frame_type = 255 /* full_frame */
          offset_delta = 4
          locals = [ class com/kwan/springbootkwan/entity/Student, int, int, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object ]
          stack = [ int, int ]
        frame_type = 255 /* full_frame */
          offset_delta = 21
          locals = [ class com/kwan/springbootkwan/entity/Student, int, int, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object ]
          stack = [ int ]
        frame_type = 255 /* full_frame */
          offset_delta = 4
          locals = [ class com/kwan/springbootkwan/entity/Student, int, int, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object ]
          stack = [ int, int ]
        frame_type = 255 /* full_frame */
          offset_delta = 21
          locals = [ class com/kwan/springbootkwan/entity/Student, int, int, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object ]
          stack = [ int ]
        frame_type = 255 /* full_frame */
          offset_delta = 4
          locals = [ class com/kwan/springbootkwan/entity/Student, int, int, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object, class java/lang/Object ]
          stack = [ int, int ]

  public java.lang.String toString();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: new           #24                 // class java/lang/StringBuilder
         3: dup
         4: invokespecial #25                 // Method java/lang/StringBuilder."<init>":()V
         7: ldc           #26                 // String Student(nameNoStatic=
         9: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        12: aload_0
        13: invokevirtual #18                 // Method getNameNoStatic:()Ljava/lang/String;
        16: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        19: ldc           #28                 // String , noneName=
        21: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        24: aload_0
        25: invokevirtual #19                 // Method getNoneName:()Ljava/lang/String;
        28: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        31: ldc           #29                 // String , id=
        33: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        36: aload_0
        37: invokevirtual #15                 // Method getId:()Ljava/lang/Integer;
        40: invokevirtual #30                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
        43: ldc           #31                 // String , question=
        45: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        48: aload_0
        49: invokevirtual #20                 // Method getQuestion:()Ljava/lang/String;
        52: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        55: ldc           #32                 // String , response=
        57: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        60: aload_0
        61: invokevirtual #21                 // Method getResponse:()Ljava/lang/String;
        64: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        67: ldc           #33                 // String , createTime=
        69: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        72: aload_0
        73: invokevirtual #22                 // Method getCreateTime:()Ljava/util/Date;
        76: invokevirtual #30                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
        79: ldc           #34                 // String , isDelete=
        81: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        84: aload_0
        85: invokevirtual #17                 // Method getIsDelete:()Ljava/lang/Integer;
        88: invokevirtual #30                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
        91: ldc           #35                 // String )
        93: invokevirtual #27                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        96: invokevirtual #36                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        99: areturn
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0     100     0  this   Lcom/kwan/springbootkwan/entity/Student;

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=3, locals=0, args_size=0
         0: ldc           #37                 // String qinyingjie2
         2: putstatic     #38                 // Field notFinal:Ljava/lang/String;
         5: bipush        20
         7: invokestatic  #39                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        10: putstatic     #40                 // Field num:Ljava/lang/Integer;
        13: new           #41                 // class java/lang/String
        16: dup
        17: ldc           #42                 // String qinyuchen
        19: invokespecial #43                 // Method java/lang/String."<init>":(Ljava/lang/String;)V
        22: putstatic     #44                 // Field newStr:Ljava/lang/String;
        25: return
      LineNumberTable:
        line 19: 0
        line 25: 5
        line 29: 13
}
Signature: #143                         // Lcom/baomidou/mybatisplus/extension/activerecord/Model<Lcom/kwan/springbootkwan/entity/Student;>;Ljava/io/Serializable;
SourceFile: "Student.java"
RuntimeVisibleAnnotations:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947

# 三.详细分析

# 1.基本信息

  1. 警告信息显示源 class 文件名称
  2. Classfile 显示了 class 文件的详细地址信息
  3. 最后一次的更新时间
  4. class 文件的字节大小
  5. MD5 值 checksum
  6. class 文件的编译来源文件
警告: 二进制文件Student包含com.kwan.springbootkwan.entity.Student
Classfile /Users/qinyingjie/Documents/idea-workspace/vue-springboot-kwan/target/classes/com/kwan/springbootkwan/entity/Student.class
  Last modified 2023-12-2; size 4370 bytes
  MD5 checksum 7683c822cf8c123129e8867436bb50ef
  Compiled from "Student.java"
1
2
3
4
5

# 2.头部信息

  1. class 文件名
  2. 继承信息
  3. 实现接口信息
  4. 次版本号
  5. 主版本号
  6. 访问标志 flags
public class com.kwan.springbootkwan.entity.Student extends com.baomidou.mybatisplus.extension.activerecord.Model<com.kwan.springbootkwan.entity.Student> implements java.io.Serializable
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
1
2
3
4

在 Java 类文件的访问标志(Access Flags)中,ACC_PUBLICACC_SUPER是两个常见的标志,它们用于描述类的访问修饰符和其他特性。

  1. ACC_PUBLIC:

    • 意义:表示该类是公共的,可以被其他类访问。
    • 解释:具有ACC_PUBLIC标志的类对于其他类是可见的,可以在同一包中或不同包中的其他类中访问。这是 Java 中最广泛使用的类访问修饰符。
  2. ACC_SUPER:

    • 意义:表示该类调用超类的方法时使用invokespecial指令。
    • 解释:ACC_SUPER标志在类文件中用于指示是否调用超类(父类)的方法时使用invokespecial指令。在 Java 虚拟机规范的早期版本中,用于实现虚拟方法调用的指令是invokespecial,它被用来调用超类中的构造方法。后来,随着 Java 语言的发展,invokespecial也用于调用私有方法、实例初始化方法和初始化方法。

    注意:

    • 在 Java 5 及以后的版本中,虚拟机对于ACC_SUPER标志的使用发生了变化,实际上这个标志的作用不再与invokespecial指令有关。它仍然会被设置,但是在实际的虚拟机实现中可能没有直接的影响。

总体而言,ACC_PUBLIC表示类是公共的,可以被其他类访问,而ACC_SUPER在过去用于指示虚拟机在方法调用时使用invokespecial指令。

# 3.常量池总结

常量池是类文件中存储常量的表,包括类的如下几种信息:

字段(Fieldref):

  • 类的字段对应的Fieldref(字段引用常量)也存放在常量池中。

方法名(类方法和父类方法Methodref):

  • 父类方法的 init 方法会被当做Methodref(方法引用常量)存放在常量池中。
  • 本类中方法引用,如 canEqual 方法的引用也会放在常量池中,主要是重写 equals 方法。

方法描述符(Utf8):

  • setId 方法的参数是 Integer,返回值是 void,会作为一个整体以 UTF-8 编码的方式存在常量池。

字符串(String或者Utf8):

  • new 出来的 qinyuchen 这个字符串会以字符串的形式存放在常量池。
  • ApiModelProperty 注解的描述会以字符串的形式存储在常量池中,区别是以 UTF-8 编码的。
  • toString 方法模版生成的字符串也是以 utf-8 编码的形式存在常量池中。
  • toString 底层是使用 StringBuilder,然后用到了 append 方法,append 方法名也会存在常量池。
  • 方法表中的属性表中的 ConstantValue 属性存储了 static final 修饰的 utf-8 编码的常量,可以直接被类访问,如qinyingjie1
  • 只被 static 修饰的字符串以 String 形式存储在常量池中,如qinyingjie2
  • 只被 final 修饰的字符串以 String 形式存储在常量池中,如qinyingjie_nameNoStatic
  • 没有被 static final 修饰的字符串以 String 形式存储在常量池中,如qinyingjie_noneName

类引用(Class):

  • Model 类是继承的类,类引用常量也会放在常量池中。
  • 使用到了 Integer,Integer 的类引用也会存在常量池。

# 4.常量池中的信息

  • 常量池中的第一位,如果有静态方法,并且静态方法中有字符串,则第一位会给这个字符串。
  • 如果没有静态方法,则第一位给父类的构造方法。

以下是一些常量池中的信息(这一部分的class常量池文件是没加静态方法getStr的文件):

  1. #1 = Methodref #35.#126:

    • 这是一个方法引用(Methodref)常量,表示对com/baomidou/mybatisplus/extension/activerecord/Model类中名为<init>且没有参数的构造方法的引用。
  2. #2 = Fieldref #7.#127:

    • 这是一个字段引用(Fieldref)常量,表示对com/kwan/springbootkwan/entity/Student类中名为id的字段的引用。
  3. #8 = Methodref #7.#133:

    • 这是一个方法引用(Methodref)常量,表示对com/kwan/springbootkwan/entity/Student类中名为canEqual的方法的引用。
  4. #32 = String #158:

    • 这是一个字符串常量,表示字符串"qinyuchen"。
  5. #35 = Class #161:

    • 这是一个类引用(Class)常量,表示对com/baomidou/mybatisplus/extension/activerecord/Model类的引用。
  6. #54 = Utf8 Lio/swagger/annotations/ApiModelProperty;:

    • 这是一个 UTF-8 编码的字符串,表示io.swagger.annotations.ApiModelProperty注解的类描述。
  7. #82 = Utf8 (Ljava/lang/Integer;)V:

    • 这是一个 UTF-8 编码的方法描述符,表示方法setId的参数为Integer,返回值为void
  8. #143 = Utf8 Student(id=:

    • 这是一个 UTF-8 编码的字符串,表示字符串"Student(id="。
  9. #165 = Utf8 append:

    • 这是一个 UTF-8 编码的字符串,表示方法append
  10. #168 = Class #168:

  • 这是一个类引用(Class)常量,表示对java/lang/Integer类的引用。

这只是常量池的一小部分,每个常量都有特定的类型和含义。常量池中的信息用于描述类的结构、字段、方法等。上述解析结果是对常量池中一些常见常量的简要说明。如果需要更详细的分析,可能需要查看整个常量池的内容。

Constant pool:
    #1 = Methodref          #35.#126      // com/baomidou/mybatisplus/extension/activerecord/Model."<init>":()V
    #2 = Fieldref           #7.#127       // com/kwan/springbootkwan/entity/Student.id:Ljava/lang/Integer;
    #3 = Fieldref           #7.#128       // com/kwan/springbootkwan/entity/Student.question:Ljava/lang/String;
    #4 = Fieldref           #7.#129       // com/kwan/springbootkwan/entity/Student.response:Ljava/lang/String;
    #5 = Fieldref           #7.#130       // com/kwan/springbootkwan/entity/Student.createTime:Ljava/util/Date;
    #6 = Fieldref           #7.#131       // com/kwan/springbootkwan/entity/Student.isDelete:Ljava/lang/Integer;
    #7 = Class              #132          // com/kwan/springbootkwan/entity/Student
    #8 = Methodref          #7.#133       // com/kwan/springbootkwan/entity/Student.canEqual:(Ljava/lang/Object;)Z
    #9 = Methodref          #7.#134       // com/kwan/springbootkwan/entity/Student.getId:()Ljava/lang/Integer;
   #10 = Methodref          #135.#136     // java/lang/Object.equals:(Ljava/lang/Object;)Z
   #11 = Methodref          #7.#137       // com/kwan/springbootkwan/entity/Student.getIsDelete:()Ljava/lang/Integer;
   #12 = Methodref          #7.#138       // com/kwan/springbootkwan/entity/Student.getQuestion:()Ljava/lang/String;
   #13 = Methodref          #7.#139       // com/kwan/springbootkwan/entity/Student.getResponse:()Ljava/lang/String;
   #14 = Methodref          #7.#140       // com/kwan/springbootkwan/entity/Student.getCreateTime:()Ljava/util/Date;
   #15 = Methodref          #135.#141     // java/lang/Object.hashCode:()I
   #16 = Class              #142          // java/lang/StringBuilder
   #17 = Methodref          #16.#126      // java/lang/StringBuilder."<init>":()V
   #18 = String             #143          // Student(id=
   #19 = Methodref          #16.#144      // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #20 = Methodref          #16.#145      // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
   #21 = String             #146          // , question=
   #22 = String             #147          // , response=
   #23 = String             #148          // , createTime=
   #24 = String             #149          // , isDelete=
   #25 = String             #150          // )
   #26 = Methodref          #16.#151      // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #27 = String             #152          // qinyingjie2
   #28 = Fieldref           #7.#153       // com/kwan/springbootkwan/entity/Student.notFinal:Ljava/lang/String;
   #29 = Methodref          #154.#155     // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #30 = Fieldref           #7.#156       // com/kwan/springbootkwan/entity/Student.num:Ljava/lang/Integer;
   #31 = Class              #157          // java/lang/String
   #32 = String             #158          // qinyuchen
   #33 = Methodref          #31.#159      // java/lang/String."<init>":(Ljava/lang/String;)V
   #34 = Fieldref           #7.#160       // com/kwan/springbootkwan/entity/Student.newStr:Ljava/lang/String;
   #35 = Class              #161          // com/baomidou/mybatisplus/extension/activerecord/Model
   #36 = Class              #162          // java/io/Serializable
   #37 = Utf8               serialVersionUID
   #38 = Utf8               J
   #39 = Utf8               ConstantValue
   #40 = Long               1l
   #42 = Utf8               name
   #43 = Utf8               Ljava/lang/String;
   #44 = String             #163          // qinyingjie1
   #45 = Utf8               notFinal
   #46 = Utf8               num
   #47 = Utf8               Ljava/lang/Integer;
   #48 = Utf8               intnum
   #49 = Utf8               I
   #50 = Integer            30
   #51 = Utf8               newStr
   #52 = Utf8               id
   #53 = Utf8               RuntimeVisibleAnnotations
   #54 = Utf8               Lio/swagger/annotations/ApiModelProperty;
   #55 = Utf8               value
   #56 = Utf8               主键id
   #57 = Utf8               question
   #58 = Utf8               问题
   #59 = Utf8               response
   #60 = Utf8               回答
   #61 = Utf8               createTime
   #62 = Utf8               Ljava/util/Date;
   #63 = Utf8               创建时间
   #64 = Utf8               isDelete
   #65 = Utf8               删除标识
   #66 = Utf8               <init>
   #67 = Utf8               ()V
   #68 = Utf8               Code
   #69 = Utf8               LineNumberTable
   #70 = Utf8               LocalVariableTable
   #71 = Utf8               this
   #72 = Utf8               Lcom/kwan/springbootkwan/entity/Student;
   #73 = Utf8               getId
   #74 = Utf8               ()Ljava/lang/Integer;
   #75 = Utf8               getQuestion
   #76 = Utf8               ()Ljava/lang/String;
   #77 = Utf8               getResponse
   #78 = Utf8               getCreateTime
   #79 = Utf8               ()Ljava/util/Date;
   #80 = Utf8               getIsDelete
   #81 = Utf8               setId
   #82 = Utf8               (Ljava/lang/Integer;)V
   #83 = Utf8               MethodParameters
   #84 = Utf8               setQuestion
   #85 = Utf8               (Ljava/lang/String;)V
   #86 = Utf8               setResponse
   #87 = Utf8               setCreateTime
   #88 = Utf8               (Ljava/util/Date;)V
   #89 = Utf8               setIsDelete
   #90 = Utf8               equals
   #91 = Utf8               (Ljava/lang/Object;)Z
   #92 = Utf8               o
   #93 = Utf8               Ljava/lang/Object;
   #94 = Utf8               other
   #95 = Utf8               this$id
   #96 = Utf8               other$id
   #97 = Utf8               this$isDelete
   #98 = Utf8               other$isDelete
   #99 = Utf8               this$question
  #100 = Utf8               other$question
  #101 = Utf8               this$response
  #102 = Utf8               other$response
  #103 = Utf8               this$createTime
  #104 = Utf8               other$createTime
  #105 = Utf8               StackMapTable
  #106 = Class              #132          // com/kwan/springbootkwan/entity/Student
  #107 = Class              #164          // java/lang/Object
  #108 = Utf8               canEqual
  #109 = Utf8               hashCode
  #110 = Utf8               ()I
  #111 = Utf8               PRIME
  #112 = Utf8               result
  #113 = Utf8               $id
  #114 = Utf8               $isDelete
  #115 = Utf8               $question
  #116 = Utf8               $response
  #117 = Utf8               $createTime
  #118 = Utf8               toString
  #119 = Utf8               <clinit>
  #120 = Utf8               Signature
  #121 = Utf8               Lcom/baomidou/mybatisplus/extension/activerecord/Model<Lcom/kwan/springbootkwan/entity/Student;>;Ljava/io/Serializable;
  #122 = Utf8               SourceFile
  #123 = Utf8               Student.java
  #124 = Utf8               Lio/swagger/annotations/ApiModel;
  #125 = Utf8               chatgpt问答实体类
  #126 = NameAndType        #66:#67       // "<init>":()V
  #127 = NameAndType        #52:#47       // id:Ljava/lang/Integer;
  #128 = NameAndType        #57:#43       // question:Ljava/lang/String;
  #129 = NameAndType        #59:#43       // response:Ljava/lang/String;
  #130 = NameAndType        #61:#62       // createTime:Ljava/util/Date;
  #131 = NameAndType        #64:#47       // isDelete:Ljava/lang/Integer;
  #132 = Utf8               com/kwan/springbootkwan/entity/Student
  #133 = NameAndType        #108:#91      // canEqual:(Ljava/lang/Object;)Z
  #134 = NameAndType        #73:#74       // getId:()Ljava/lang/Integer;
  #135 = Class              #164          // java/lang/Object
  #136 = NameAndType        #90:#91       // equals:(Ljava/lang/Object;)Z
  #137 = NameAndType        #80:#74       // getIsDelete:()Ljava/lang/Integer;
  #138 = NameAndType        #75:#76       // getQuestion:()Ljava/lang/String;
  #139 = NameAndType        #77:#76       // getResponse:()Ljava/lang/String;
  #140 = NameAndType        #78:#79       // getCreateTime:()Ljava/util/Date;
  #141 = NameAndType        #109:#110     // hashCode:()I
  #142 = Utf8               java/lang/StringBuilder
  #143 = Utf8               Student(id=
  #144 = NameAndType        #165:#166     // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #145 = NameAndType        #165:#167     // append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #146 = Utf8               , question=
  #147 = Utf8               , response=
  #148 = Utf8               , createTime=
  #149 = Utf8               , isDelete=
  #150 = Utf8               )
  #151 = NameAndType        #118:#76      // toString:()Ljava/lang/String;
  #152 = Utf8               qinyingjie2
  #153 = NameAndType        #45:#43       // notFinal:Ljava/lang/String;
  #154 = Class              #168          // java/lang/Integer
  #155 = NameAndType        #169:#170     // valueOf:(I)Ljava/lang/Integer;
  #156 = NameAndType        #46:#47       // num:Ljava/lang/Integer;
  #157 = Utf8               java/lang/String
  #158 = Utf8               qinyuchen
  #159 = NameAndType        #66:#85       // "<init>":(Ljava/lang/String;)V
  #160 = NameAndType        #51:#43       // newStr:Ljava/lang/String;
  #161 = Utf8               com/baomidou/mybatisplus/extension/activerecord/Model
  #162 = Utf8               java/io/Serializable
  #163 = Utf8               qinyingjie1
  #164 = Utf8               java/lang/Object
  #165 = Utf8               append
  #166 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #167 = Utf8               (Ljava/lang/Object;)Ljava/lang/StringBuilder;
  #168 = Utf8               java/lang/Integer
  #169 = Utf8               valueOf
  #170 = Utf8               (I)Ljava/lang/Integer;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

# 5.canEqual

canEqual 方法通常用于实现 Java 中的 equals 方法。在实现类的 equals 方法时,通常需要遵循一些约定,其中之一是覆盖 equals 方法时也要覆盖 hashCode 方法。在实现 equals 方法时,需要比较两个对象的类型,以防止比较不同类型的对象。

canEqual 方法用于检查传入的对象是否是相同类的实例,这是为了确保在比较两个对象时不会因为类型不同而导致错误。通常,canEqual 方法的实现会使用 instanceof 运算符来进行类型检查。

protected boolean canEqual(final Object other) {
        return other instanceof Student;
}
1
2
3

# 6.构造方法说明

  • class 文件中方法会被{}括起来
  • Student()标识是 Student 类的构造函数
{
  public com.kwan.springbootkwan.entity.Student();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method com/baomidou/mybatisplus/extension/activerecord/Model."<init>":()V
         4: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这是一个默认构造方法的字节码表示,对应于 com.kwan.springbootkwan.entity.Student 类的构造方法。下面是对该字节码的详细解释:

  • public com.kwan.springbootkwan.entity.Student();

    • 这是构造方法的声明,表示一个公共的无参数构造方法,属于 com.kwan.springbootkwan.entity.Student 类。
  • descriptor: ()V

    • 描述符表示方法的签名,这里 () 表示无参数,V 表示返回类型为 void
  • flags: ACC_PUBLIC

    • 表示该方法是公共的。
  • Code:

    • 下面是方法的字节码指令。
  • stack=1, locals=1, args_size=1

    • 这是关于操作数栈局部变量方法参数大小的信息。
    • 对于无参数方法,这三个值通常都是 1。
    • stack表示方法的操作数栈的最大深度,即在方法执行期间,最多同时存在多少个数值在操作数栈上。对于无参数方法,通常只需一个槽位来存储当前对象的引用(this)。
    • locals表示局部变量表的大小,即方法在执行期间可以使用的局部变量槽位数量。对于无参数方法,通常只需一个槽位来存储当前对象的引用(this)。
    • args_size表示方法的参数数量。对于无参数方法,参数数量为 1,即当前对象引用(this)。
  • 0: aload_0

    • 将当前对象引用(this)加载到操作数栈上。
    • 0 代表字节码中的第 0 条指令。偏移量是 0。
  • 1: invokespecial #1

    • 调用父类构造方法。invokespecial 是用于调用特殊方法(比如构造方法、私有方法)的指令。#1 是对常量池中索引为 1 的方法引用的引用。
    • 1 代表字节码中的第 1 条指令。偏移量是 1。
  • 4: return

    • 返回,结束方法执行。
    • 4 代表字节码中的第 1 条指令。偏移量是 4。
  • LineNumberTable:

    • 表示源代码行号信息。
  • line 12: 0

    • 在源代码的第 12 行,对应于字节码的第 0 指令。
  • LocalVariableTable:

    • 表示局部变量表信息。
  • Start Length Slot Name Signature

    • 描述局部变量表的开始位置、长度、槽位、变量名和变量签名。
  • 0 5 0 this Lcom/kwan/springbootkwan/entity/Student;

    • 表示在方法执行期间,槽位为 0 的局部变量是当前对象引用,变量名为 this,类型为 Lcom/kwan/springbootkwan/entity/Student;

总体而言,这段字节码表示 com.kwan.springbootkwan.entity.Student 类的公共无参数构造方法,其中通过 aload_0 指令加载当前对象引用到操作数栈上,然后通过 invokespecial 指令调用父类构造方法,最后通过 return 指令返回。

# 7.get 方法说明

getId 和构造函数方法过程类似,差异不大,可以类比分析,这里具体分析省略。

public java.lang.Integer getId();
    descriptor: ()Ljava/lang/Integer;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #2                  // Field id:Ljava/lang/Integer;
         4: areturn
      LineNumberTable:
        line 28: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;
1
2
3
4
5
6
7
8
9
10
11
12
13

# 8.set 方法说明

public void setId(java.lang.Integer);
    descriptor: (Ljava/lang/Integer;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #2                  // Field id:Ljava/lang/Integer;
         5: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   Lcom/kwan/springbootkwan/entity/Student;
            0       6     1    id   Ljava/lang/Integer;
    MethodParameters:
      Name                           Flags
      id                             final
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

这段字节码对应于一个 Java 方法,该方法名为 setId,参数为一个 java.lang.Integer 类型的对象。下面是对这段字节码的详细解析:

  • public void setId(java.lang.Integer);

    • 这是方法的声明,表示一个公共的无返回值方法,名为 setId,接受一个 java.lang.Integer 类型的参数。
  • descriptor: (Ljava/lang/Integer;)V

    • 方法的描述符,指定了方法的签名。这里 (Ljava/lang/Integer;)V 表示方法接受一个 java.lang.Integer 类型的参数,返回类型为 void
  • flags: ACC_PUBLIC

    • 表示该方法是公共的。
  • Code:

    • 下面是方法的字节码指令。
  • stack=2, locals=2, args_size=2

    • stack=2 表示方法的操作数栈的最大深度是 2。
    • locals=2 表示局部变量表的大小是 2。
    • args_size=2 表示方法的参数数量是 2。
  • 0: aload_0

    • 将当前对象的引用(this)加载到操作数栈上。
  • 1: aload_1

    • 将方法参数 id 的值加载到操作数栈上。
  • 2: putfield #2

    • 将操作数栈顶的值(id)赋值给对象的字段。#2 表示常量池中索引为 2 的字段引用。
  • 5: return

    • 返回,结束方法执行。
  • LineNumberTable:

    • 表示源代码行号信息。
  • line 12: 0

    • 在源代码的第 12 行,对应于字节码的第 0 指令。
  • LocalVariableTable:

    • 表示局部变量表信息。
  • Start Length Slot Name Signature

    • 描述局部变量表的开始位置、长度、槽位、变量名和变量签名。
  • 0 6 0 this Lcom/kwan/springbootkwan/entity/Student;

    • 表示在方法执行期间,槽位为 0 的局部变量是当前对象引用,变量名为 this,类型为 Lcom/kwan/springbootkwan/entity/Student;
  • 0 6 1 id Ljava/lang/Integer;

    • 表示在方法执行期间,槽位为 1 的局部变量是参数 id,类型为 Ljava/lang/Integer;
  • MethodParameters:

    • 表示方法参数的信息。
  • Name Flags

    • 参数的名称和标志。
  • id final

    • 参数的名称为 id,并且标记为 final

# 9.常量方法

static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=3, locals=0, args_size=0
         0: ldc           #27                 // String qinyingjie2
         2: putstatic     #28                 // Field notFinal:Ljava/lang/String;
         5: bipush        20
         7: invokestatic  #29                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        10: putstatic     #30                 // Field num:Ljava/lang/Integer;
        13: new           #31                 // class java/lang/String
        16: dup
        17: ldc           #32                 // String qinyuchen
        19: invokespecial #33                 // Method java/lang/String."<init>":(Ljava/lang/String;)V
        22: putstatic     #34                 // Field newStr:Ljava/lang/String;
        25: return
      LineNumberTable:
        line 19: 0
        line 21: 5
        line 25: 13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 10.操作数栈和局部变量表区别?

stack=1, locals=1, args_size=1

  • 这是关于操作数栈局部变量方法参数大小的信息。
  • 对于无参数方法,这三个值通常都是 1。
  • stack表示方法的操作数栈的最大深度,即在方法执行期间,最多同时存在多少个数值在操作数栈上。对于无参数方法,通常只需一个槽位来存储当前对象的引用(this)。
  • locals表示局部变量表的大小,即方法在执行期间可以使用的局部变量槽位数量。对于无参数方法,通常只需一个槽位来存储当前对象的引用(this)。
  • args_size表示方法的参数数量。对于无参数方法,参数数量为 1,即当前对象引用(this)。

操作数栈(Operand Stack)和局部变量表(Local Variable Table)是 Java 虚拟机(JVM)中两个关键的数据结构,用于支持方法的执行。它们在存储和管理数据的方式上有一些重要的区别:

操作数栈(Operand Stack):

  • 作用: 操作数栈是一个后进先出(LIFO)的栈,用于存储方法执行期间的临时数据中间结果。它是一种运算时的工作区,用于保存方法调用过程中产生的数据以及进行操作数的压栈弹栈操作。
  • 访问: JVM 的字节码指令通常包括对操作数栈的读写操作。例如,将数据推入操作数栈、弹出数据、进行算术运算等。
  • 生命周期: 操作数栈中的数据生命周期短暂,仅在方法的执行期间有效。当方法调用结束时,操作数栈的内容也被销毁。

局部变量表(Local Variable Table):

  • 作用: 局部变量表是一个数组,用于存储方法中的局部变量。局部变量包括方法参数临时变量以及在方法体内部定义其他变量。与操作数栈不同,局部变量表的数据在方法的整个生命周期内都是可访问的。
  • 访问: 局部变量表通过索引来访问,而不像操作数栈那样通过栈顶指针。变量的访问是直接的,通过索引来定位,而不需要像操作数栈那样进行栈顶的推入和弹出操作。
  • 生命周期: 局部变量表中的数据的生命周期长于操作数栈,它们在整个方法的执行过程中都可以被访问。

总的来说,操作数栈主要用于执行方法过程中的计算和操作,而局部变量表则用于存储方法中的局部变量。这两个数据结构协同工作,支持方法的正确执行。

# 11.方法表总结

  • 静态方法放在第一位,然后是构造方法,最后是其他方法
  • 方法声明,方法表用{}括起来,里面都是方法
  • 方法描述符和方法签名(descriptor)
  • 方法访问标志(flags)
  • 方法的字节码指令(code)
  • 方法的参数信息(MethodParameters)
{
  public com.kwan.springbootkwan.entity.Student();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method com/baomidou/mybatisplus/extension/activerecord/Model."<init>":()V
         4: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 12.方法的字节码指令

方法的字节码指令(code)包含如下内容

  • 操作数栈
  • 局部变量表
  • 方法参数大小
  • 源代码行号信息
  • 局部变量表的详细信息
  • 方法参数的详细信息
{
  public com.kwan.springbootkwan.entity.Student();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method com/baomidou/mybatisplus/extension/activerecord/Model."<init>":()V
         4: return
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/kwan/springbootkwan/entity/Student;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • Code:

    • 下面是方法的字节码指令。
  • stack=1, locals=1, args_size=1

    • 这是关于操作数栈局部变量方法参数大小的信息。
    • 对于无参数方法,这三个值通常都是 1。
    • stack表示方法的操作数栈的最大深度,即在方法执行期间,最多同时存在多少个数值在操作数栈上。对于无参数方法,通常只需一个槽位来存储当前对象的引用(this)。
    • locals表示局部变量表的大小,即方法在执行期间可以使用的局部变量槽位数量。对于无参数方法,通常只需一个槽位来存储当前对象的引用(this)。
    • args_size表示方法的参数数量。对于无参数方法,参数数量为 1,即当前对象引用(this)。
  • 0: aload_0

    • 将当前对象引用(this)加载到操作数栈上。
    • 0 代表字节码中的第 0 条指令。偏移量是 0。
  • 1: invokespecial #1

    • 调用父类构造方法。invokespecial 是用于调用特殊方法(比如构造方法、私有方法)的指令。#1 是对常量池中索引为 1 的方法引用的引用。
    • 1 代表字节码中的第 1 条指令。偏移量是 1。
  • 4: return

    • 返回,结束方法执行。
    • 4 代表字节码中的第 1 条指令。偏移量是 4。
  • LineNumberTable:

    • 表示源代码行号信息。
  • line 12: 0

    • 在源代码的第 12 行,对应于字节码的第 0 指令。
  • LocalVariableTable:

    • 表示局部变量表信息。
  • Start Length Slot Name Signature

    • 描述局部变量表的开始位置、长度、槽位、变量名和变量签名。
  • 0 5 0 this Lcom/kwan/springbootkwan/entity/Student;

    • 表示在方法执行期间,槽位为 0 的局部变量是当前对象引用,变量名为 this,类型为 Lcom/kwan/springbootkwan/entity/Student;

# 四.Class 文件结构

# 1.谈谈你对 class 文件的了解

类型 名称 数量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attributes_count 1
attribute_info attributes attributes_count

以上是 Java 类文件格式中的各个部分的名称、类型和数量的展示。其中:

  • u4 表示 4 个字节无符号整数
  • u2 表示 2 个字节无符号整数

constant_pool_count: 表示常量池中的常量数量(不包括占用两个位置的 long 和 double 类型常量,所以要减去 1)

在 Java 类文件格式中,常量池是一个重要的部分,它包含了类、接口、字段、方法等信息的符号引用和字面量常量。其他部分则包括类版本信息、访问标志、接口列表、字段表、方法表和属性表等。

# 2.fields 和 attributes 区别

在 Java 的 Class 文件中,fields(字段表)和attributes(属性表)是两个不同的部分,用于描述类或接口的结构和特性。

  1. Fields(字段表):
    • fields部分用于描述接口中定义的字段(成员变量)信息。
    • 每个字段都包含了字段的访问修饰符、字段名称、字段类型等信息。
    • 字段表中记录了类或接口中所有的字段,无论是静态字段还是实例字段,包括公共的、私有的、保护的和默认访问权限的字段。
  2. Attributes(属性表):
    • attributes部分用于描述字段方法代码等部分的额外属性信息。
    • 属性表中包含了各种不同类型的属性,这些属性可以用于存储额外的元数据,供 Java 虚拟机和其他工具使用。
    • 在类级别,属性表中可能包含SourceFile(源文件名)、InnerClasses(内部类信息)、EnclosingMethod(外部类和方法信息)等属性。
    • 在字段级别,属性表中可能包含ConstantValue(常量值)、Synthetic(合成字段标记)等属性。
    • 在方法级别,属性表中可能包含Code(字节码)、Exceptions(异常表)、LineNumberTable(行号表)等属性。

总结: fields部分记录了类或接口中定义的字段信息,而attributes部分用于描述类、字段、方法或代码等部分的额外属性信息。fields主要描述类的结构,而attributes主要用于存储附加的元数据和信息,用于支持 Java 虚拟机和其他工具的功能。

# 3.DemoTest 解析

class 文件是以一组 8 个字节为基础单位的二进制流,各个数据项严格按照顺序紧凑排列在文件中,中间没有任何分隔符,这使得 class 文件存储的都是程序运行的必要数据,没有空隙存在。

class 文件格式采用一种类似 c 语言结构体的伪结构体老存储数据,这种伪结构体只包含 2 种数据类型:无符号数和表。

无符号数属于基本的数据类型,以 u1,u2,u4,u8 分别来表示 1 个字节,2 个字节,4 个字节,8 个字节的无符号数.无符号数可以用来描述数字,索引引用,数量值或者按照 utf-8 编码构成的字符串值。

表是由多个无符号数或者其他表作为数据项构成的复合型数据结构,为了便于区分,表通常以_info 结尾.用于描述复杂的结构,整个 class 文件可以看成一个大表。

image-20230727204139856

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;//接口数(2位,所以一个类最多65535个接口)
    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];//属性表集合
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 4.class 文件中的魔数和主次版本号?

每个 class 文件的头 4 个字节被称为魔数,它的唯一作用是确定这个文件是否能为一个虚拟机所接受的 class 文件。紧接着是 class 文件的版本号,第五和第六字节是次版本号,第七第八是主版本号,java 的版本号是从 45 开始的,jdk1.1 开始每个 jdk 大版本发布主版本号向上加 1。

image-20230727210121435

# 5.为什么常量池计数器从 1 开始

由于常量池中常量的数量是不固定的,所以常量池中的入口需要放置一项 u2 类型的数据,代表常量池容量计数器,constant_pool_count,这个计数器是从 1 开始的不是从 0 开始的,如下图所示,十六进制数 0x0016,十进制就是 22,代表着常量池中有 21 项常量,索引范围为 1~21。

第 0 项表示不引用任何一个常量池项目.class 文件只有常量池的容量是从 1 开始的,对于其他的集合类型,包括接口索引集合,字段表集合,方法表集合等的容量计数器都是从 0 开始的。

  • 匿名内部类本身没有类名称,进行名称引用时,会将 index 指向 0
  • Object 类的 class 文件父类索引指向 0

image-20230727210145421

# 6.class 文件常量池中存放的是什么内容?

常量池中主要存放两大类常量:字面量和符号引用

字面量比较接近于 java 语言层面的常量概念,如文本字符串,被声明为 final 的常量值等

符号引用则属于偏编译方面的概念,主要包含以下几类常量:

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符
  • 方法句柄和方法类型
  • 动态调用点和动态常量

image-20230727210348919

# 7.常量池的项目类型?

十四种常量都有自己的结构.

image-20231022231003264

CONSTANT_Class_info: 代表类或接口的符号引用.数据结构如下.

tag 标志位用于区分常量类型,name_index 是一个索引值,指向常量池中一个 CONSTANT_Utf8_info 类型的常量.此常量代表了这个类或接口的全限定名.

image-20231020114029553

CONSTANT_Utf8_info: 的数据结构如下

  • tag 是标志位区分类型

  • length 代表数据长度,最大为 65535

  • bytes 代表实际数据

image-20231022231024181

常量 项目 类型 描述
CONSTANT_Utf8_info tag u1 值为 1
length u2 UTF-8 编码的字符串占用的字节数
bytes u1 长度为 length 的 UTF-8 编码的字符串
CONSTANT_Integer_info tag u1 值为 3
bytes u4 按照高位在前存储的 int 值
CONSTANT_Float_info tag u1 值为 4
bytes u4 按照高位在前存储的 float 值
CONSTANT_Long_info tag u5 值为 5
bytes u8 按照高位在前存储的 long 值
CONSTANT_Double_info tag u1 值为 6
bytes u8 按照高位在前存储的 double 值
CONSTANT_Class_info tag u1 值为 7
index u2 指向全限定名常量项的索引
CONSTANT_String_info tag u1 值为 8
index u2 指向字符串字面量的索引
CONSTANT_Fieldref_info tag u1 值为 9
index u2 指向声明字段的类或者接口描述符 CONSTANT_Class_info 的索引项
index u2 指向字段描述符 CONSTANT_NameAndType 的索引项
CONSTANT_Methodref_info tag u1 值为 10
index u2 指向声明方法的类描述符 CONSTANT_ Class_info 的索引项
index u2 指向名称及类型描述符 CONSTANT_NameAndType 的索引项
CONSTANT_Interface_Methodref _info tag u1 值为 11
index u2 指向声明方法的接口描述符 CONSTANT_Class_info 的索引项
index u2 指向名称及类型描述符 CONSTANT_NameAndType 的索引项
CONSTANT_NameAndType_info tag u1 值为 12
index u2 指向该字段或方法名称常量项的索引
index u2 指向该字段或方法描述符常量项的索引
CONSTANT_MethodHandle_info tag u1 值为 15
reference_kind u1 值必须在 1~9 之间(包括 1 和 9)它决定了方法句柄的类型,方法句柄类型的值表示方法句柄的字节码行为
reference_index u2 值必须是对常量池的有效索引
CONSTANT_MethodType_info tag u1 值为 16
descriptor_index u2 值必须是对常量池的有效索引,常量池在该索引处的项必须是 CONSTANT Utf8info 结构,表示方法的描述符
CONSTANT_Invoke_Dynamic_info tag u1 值为 18
bootstrap_method_attr_index u2 值必须是对当前 Class 文件中引导方法表的 bootstrap_methods 数组的有效索引
name_and_type_index u2 值必须是对当前常量池的有效索引,常量池在该索引处的项必须是 CONSTANT_NameAndType_info 结构,表示方法名和方法描述符

# 8.java 字段名和方法名长度限制?

字段名和方法名都存储在常量池中

存储这 2 个名称需要用到常量池中的 constant_utf8_info 类型来存储,以下是 constant_utf8_info 的存储结构,

image-20231022231037848

constant_utf8_info 的最大长度也是 java 中方法名字段名的长度,这里最大长度就是 length 的最大值,即 u2 类型能表达的最大值为 65535,所以 java 程序中定义了超过 64kb 英文字符的变量或者方法名,即使规则和名字符号全部合法,也无法编译。

  • 1kb=1024 字节
  • 64kb=65536 字节是临街值,不能等于 64kb

# 9.class 文件的访问标志作用?

常量池结束后,是 2 个字节的访问标志,用于标示类和接口层次的访问信息.包括这个 class 是类还是接口,是否定义为 public 类型,是否定义为 abstract 类型,如果是类的话,是否声明为 final 等等。

image-20230727210842600

image-20230727210859601

# 10.类索引、父类索引、接口索引集合作用

类索引(this_class)和父类索引(super_class)都是一个 u2 类型的数据。而接口索引集合(interfaces)是一组 u2 类型的数据集合,class 文件中由这三项数据来确定该类的继承实现关系。

image-20230727211041376

类索引用于确定这个类的全限定名(全限定名称存储于常量池),父类索引用于确定这个类的父类的全限定名.这里说的索引,是指向常量池中的 constant_class_info 类型,constant_class_info 又指向了 constant_utf8_info 从而确定全限定名。

由于 java 语言不支持多继承,所以父类索引只有一个,除了 java.lang.Object 之外,所有的 java 类都有父类,且父类索引都不为 0,接口索引集合就是用来描述这个类实现了哪些接口,这些被实现的接口将按 implements 关键字后的接口顺序从左到右排列在接口索引集合中。

类索引,父类索引,接口索引集合都按顺序排列在访问标志之后,类索引和父类索引,用 2 个 u2 类型的值表示,他们各自指向一个 constant_class_info 的类描述符常量,通过 constant_class_info 类型的常量中的索引值可以找到定义在 constant_utf8_info 类型的常量中的全限定名字符串。

image-20231022231054267

# 11.class 文件的字段表存储的什么信息?

image-20231022231120789

字段表(field_info)用于描述接口或者类中声明的变量,java 语言中的字段包括类级变量以及实例级变量,但不包含在方法内部声明的局部变量。

字段表存储的是变量的修饰符+字段的描述符索引(索引指向常量池)+字段名称索引(索引指向常量池).

修饰符:字段可以包括的修饰符有字段的作用域(public,private,protected 修饰符),是实例变量还是类变量(static 修饰符),可变性(final),并发可见性(volatile 修饰符,是否强制从主内存读写),可否被序列化(transient 修饰符)等。

描述符:字段类型。

public final static String number=“1”,public final 和 static 是访问修饰符access_flags,这些都存在 class 文件的字段表中,String 是字段描述符,存放于常量池中的 name_index,number 是字段的名称 descrip_index,存放于常量池,这两部分的关联,是通过字段表的 name_index 指向常量池中的字段名称 numberdescrip_index 指向常量池中的描述符。

image-20230727211618977

# 12.class 文件的方法表存储的什么?

class 文件存储格式中对方法的描述,采用的方式和字段表一致,方法表的结构和字段表一致,包含访问标示access_flags,名称索引name_index,描述符索引descriptor_index,属性表集合attributes

image-20230727211733376

image-20230727211747384

# 13.class 文件中的属性表?

  • ConstantValue 是在字段表下使用的;
  • Code 属性是在方法表下使用的;

image-20230727211915669

属性表在 class 文件字段表方法表都有自己的属性表集合,以描述某些场景专有的信息。与 class 文件中其他数据项要求严格的顺序,长度和内容不同,属性表限制稍微宽松一些,不再要求严格的顺序。只要属性名不重复,允许写入自己定义的属性信息。

对于每一个属性,它的名称都是从常量池中引用一个 constant_utf8_info 类型的常量来表示,而属性值的结构是完全自定义的,只需要通过一个 u4 的长度属性去说明属性值所占用的字节的位数即可。

image-20231022231142832

Code 属性:java 代码经过 javac 编译之后,最终变成字节码指令存储在 code 属性中。code 属性出现在方法表的属性集合中。但并非所有的方法表都必须存在这个属性,譬如接口和抽象类的方法就不存在 code 属性,如果方法表有 code 属性存在,那么它的结构如下:

image-20230727212132743

LineNumberTable 属性:LineNumberTable 属性用于描述 java 源码的行号和字节码行号之间的偏移量的对应关系。它不是运行时必需的属性,但默认会生成到 class 文件之中,可以在 javac 中使用-g:none 或者-g:lines 选项来取消或者要求生成这项信息,如果选择不生成 LineNumberTable 属性,对程序的影响是,抛出异常时,堆栈中将不显示出错的行号,并且在调试程序的时候,也无法按照源码行来设置断点。

image-20230727212323021

ConstantValue 属性:主要作用是为静态变量赋值,只有被 static 修饰的变量才能使用这个属性。int x=123 和 static int x=123 这样的定义在 java 中很常见,但虚拟机对这 2 种方式的赋值的方式和时刻有所不同。对于非 static 修饰的变量,在实例构造器 init 方法中进行赋值。对于类变量,有 2 种方式,通过类构造器的 clinit 方法赋值或者使用 ConstantValue 属性。如果同时使用 final 和 static 关键字修饰同一个变量,并且变量类型是基本数据类型或者 String,就会使用 ConstantValue 属性来进行初始化,如果没有用 final 修饰,或者非基本类型或者字符串,会在构造器 clinit 方法中初始化。

//举例说明
public static final String NUMBER=111111;
1
2

static 和 final 同时修饰的变量,会在编译的过程中把 NUBER 的值进行初始化,放到 ConstanValue 属性中,否则需要到最后一步初始化时在 clinit 方法中进行初始化。

image-20230727212648804

上次更新: 10/29/2024, 10:27:50 AM