Class文件-03
1.基本信息
- 警告信息显示源 class 文件名称
- Classfile 显示了 class 文件的详细地址信息
- 最后一次的更新时间
- class 文件的字节大小
- MD5 值 checksum
- 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"
2.头部信息
- class 文件名
- 继承信息
- 实现接口信息
- 次版本号
- 主版本号
- 访问标志 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
在 Java 类文件的访问标志(Access Flags)中,
ACC_PUBLIC
和ACC_SUPER
是两个常见的标志,它们用于描述类的访问修饰符和其他特性。
ACC_PUBLIC:
- 意义:表示该类是公共的,可以被其他类访问。
- 解释:具有
ACC_PUBLIC
标志的类对于其他类是可见的,可以在同一包中或不同包中的其他类中访问。这是 Java 中最广泛使用的类访问修饰符。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 = Methodref #35.#126:
- 这是一个
方法引用(Methodref)常量
,表示对com/baomidou/mybatisplus/extension/activerecord/Model
类中名为<init>
且没有参数的构造方法的引用。
- 这是一个
-
#2 = Fieldref #7.#127:
- 这是一个字段引用(Fieldref)常量,表示对
com/kwan/springbootkwan/entity/Student
类中名为id
的字段的引用。
- 这是一个字段引用(Fieldref)常量,表示对
-
#8 = Methodref #7.#133:
- 这是一个方法引用(Methodref)常量,表示对
com/kwan/springbootkwan/entity/Student
类中名为canEqual
的方法的引用。
- 这是一个方法引用(Methodref)常量,表示对
-
#32 = String #158:
- 这是一个字符串常量,表示字符串"qinyuchen"。
-
#35 = Class #161:
- 这是一个类引用(Class)常量,表示对
com/baomidou/mybatisplus/extension/activerecord/Model
类的引用。
- 这是一个类引用(Class)常量,表示对
-
#54 = Utf8 Lio/swagger/annotations/ApiModelProperty;:
- 这是一个 UTF-8 编码的字符串,表示
io.swagger.annotations.ApiModelProperty
注解的类描述。
- 这是一个 UTF-8 编码的字符串,表示
-
#82 = Utf8 (Ljava/lang/Integer;)V:
- 这是一个 UTF-8 编码的方法描述符,表示方法
setId
的参数为Integer
,返回值为void
。
- 这是一个 UTF-8 编码的方法描述符,表示方法
-
#143 = Utf8 Student(id=:
- 这是一个 UTF-8 编码的字符串,表示字符串"Student(id="。
-
#165 = Utf8 append:
- 这是一个 UTF-8 编码的字符串,表示方法
append
。
- 这是一个 UTF-8 编码的字符串,表示方法
-
#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;
5.canEqual
canEqual
方法通常用于实现 Java 中的 equals 方法。在实现类的 equals 方法时,通常需要遵循一些约定,其中之一是覆盖 equals
方法时也要覆盖 hashCode
方法。在实现 equals
方法时,需要比较两个对象的类型,以防止比较不同类型的对象。
canEqual
方法用于检查传入的对象是否是相同类的实例,这是为了确保在比较两个对象时不会因为类型不同而导致错误。通常,canEqual
方法的实现会使用 instanceof
运算符来进行类型检查。
protected boolean canEqual(final Object other) {
return other instanceof Student;
}
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;
}
这是一个默认构造方法的字节码表示,对应于 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;
。
- 表示在方法执行期间,槽位为 0 的局部变量是当前对象引用,变量名为
总体而言,这段字节码表示 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;
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
这段字节码对应于一个 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 的局部变量是当前对象引用,变量名为
-
0 6 1 id Ljava/lang/Integer;
:- 表示在方法执行期间,槽位为 1 的局部变量是参数
id
,类型为Ljava/lang/Integer;
。
- 表示在方法执行期间,槽位为 1 的局部变量是参数
-
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
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;
}
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;
}
-
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;
。
- 表示在方法执行期间,槽位为 0 的局部变量是当前对象引用,变量名为
- 点赞
- 收藏
- 关注作者
评论(0)