Java 虚拟机原理Class 字节码二进制文件分析 三 ( 访问和修饰标志 | 类索引 | 父类索引 | 接口计数器 | 接口表 | 字段计数器 | 字段表 )
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 虚拟机原理Class 字节码二进制文件分析 三 ( 访问和修饰标志 | 类索引 | 父类索引 | 接口计数器 | 接口表 | 字段计数器 | 字段表 )相关的知识,希望对你有一定的参考价值。
前言
上一篇博客 【Java 虚拟机原理】Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 ) ;
分析到 Student.class 字节码文件的如下选中部分是常量池数据 ;
本篇博客中 , 继续向后分析 字节码对应数据 ;
分析的原始数据是 【Java 虚拟机原理】Class 字节码二进制文件分析 一 ( 字节码文件附加信息 | 魔数 | 次版本号 | 主版本号 | 常量池个数 ) 二、字节码文件示例 章节中的 Java 源码 , Class 字节码 , 字节码附加信息 ;
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
字节码附加信息 :
D:\\jvm>javap -v Student.class
Classfile /D:/jvm/Student.class
Last modified 2021-9-4; size 392 bytes
MD5 checksum 8b9bb897bb8cf2a8addf04be5b7b915f
Compiled from "Student.java"
public class Student
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #4.#17 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#18 // Student.name:Ljava/lang/String;
#3 = Class #19 // Student
#4 = Class #20 // java/lang/Object
#5 = Utf8 name
#6 = Utf8 Ljava/lang/String;
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 getName
#12 = Utf8 ()Ljava/lang/String;
#13 = Utf8 setName
#14 = Utf8 (Ljava/lang/String;)V
#15 = Utf8 SourceFile
#16 = Utf8 Student.java
#17 = NameAndType #7:#8 // "<init>":()V
#18 = NameAndType #5:#6 // name:Ljava/lang/String;
#19 = Utf8 Student
#20 = Utf8 java/lang/Object
{
public Student();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
public java.lang.String getName();
descriptor: ()Ljava/lang/String;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: getfield #2 // Field name:Ljava/lang/String;
4: areturn
LineNumberTable:
line 5: 0
public void setName(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 #2 // Field name:Ljava/lang/String;
5: return
LineNumberTable:
line 9: 0
line 10: 5
}
SourceFile: "Student.java"
一、访问和修饰标志
access_flags ( 访问和修饰标志 ) : 常量池后面的
2
2
2 位就是 访问和修饰标志 ; 访问 和 修饰标志 00 21
; 表示 类 / 接口 的 访问权限 / 基础属性 ;
根据下面两个表解读 访问和修饰标志 ;
访问和修饰标志 00 21
; 这是根据上述表格中的值进行位运算得到的 ;
这是 ACC_SUPER 0x0200
和 ACC_PUBLIC 0x0001
两个值进行或运算 , 得出的值 0x0021
;
在 字节码附加信息 中的 次版本号 , 主版本号 , 后跟着的就是 访问和修饰标志 ACC_PUBLIC, ACC_SUPER
, 就是根据这里的
2
2
2 个字节的信息得出的 ;
public class Student
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
二、类索引
this_class ( 类索引 ) : 在 access_flags ( 访问和修饰标志 ) 后面的 2 2 2 字节就是 类索引 ; 这个值必须是 常量池 中的有效索引值 , 并且还要是 CONSTANT_Class_Info 类型的常量 ;
值为 00 03
, 也就是对应常量池中的 #3
常量 ;
常量池中的 #3
索引是 Student 类 ; 参考 【Java 虚拟机原理】Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 ) 二、常量池字节码文件分析 3、常量池 #3 常量分析 章节 ;
Constant pool:
#1 = Methodref #4.#17 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#18 // Student.name:Ljava/lang/String;
#3 = Class #19 // Student
后面的字节码数据, 基本都是指向了常量池中的一些引用 ;
三、父类索引
super_class ( 父类索引 ) : 在 this_class ( 类索引 ) 后面的 2 2 2 字节就是 父类索引 ; 这个值必须是 常量池 中的有效索引值 , 并且还要是 CONSTANT_Class_Info 类型的常量 ;
值为 00 04
, 也就是对应常量池中的 #3
常量 ;
常量池中的 #4
索引是 java/lang/Object 类 ; 参考 【Java 虚拟机原理】Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 ) 二、常量池字节码文件分析 4、常量池 #4 常量分析 章节 ;
Constant pool:
#4 = Class #20 // java/lang/Object
后面的字节码数据, 基本都是指向了常量池中的一些引用 ;
四、接口计数器
interface_count ( 接口计数器 ) : 在 super_class ( 父类索引 ) 后面的 2 2 2 字节就是 接口计数器 ; 表示 当前 类 的 直接 父类 或 接口 数 , 间接的不算 ;
值为 00 00
, 也就是没有实现任何接口 , 接口数为
0
0
0 ;
五、接口表
interfaces ( 接口表 ) : 这里注意 , 如果接口个数大于 0 0 0 才有字段表 , 如果接口个数为 0 0 0 , 根本没有这个字段 ;
本示例中 接口个数为 0 0 0 , 后面没有字段表 , 接口计数器 后面的 2 2 2 字节是 字段计数器 ;
六、字段计数器
fields_count ( 字段计数器 ) : 在 接口计数器 / 接口表 后面的 2 2 2 字节就是 字段计数器 ; 表示 当前 类 的 字段 数 ;
值为 00 01
, 表示当前类有
1
1
1 个字段 ;
七、字段表
fields ( 字段表 ) : fields_count ( 字段计数器 ) 后的若干字节 , 就是字段表信息 ;
以上是关于Java 虚拟机原理Class 字节码二进制文件分析 三 ( 访问和修饰标志 | 类索引 | 父类索引 | 接口计数器 | 接口表 | 字段计数器 | 字段表 )的主要内容,如果未能解决你的问题,请参考以下文章
Java 虚拟机原理Class 字节码二进制文件分析 四 ( 字段表数据结构 | 字段表详细分析 | 访问标志 | 字段名称 | 字段描述符 | 属性项目 )
Java 虚拟机原理Class 字节码二进制文件分析 三 ( 访问和修饰标志 | 类索引 | 父类索引 | 接口计数器 | 接口表 | 字段计数器 | 字段表 )
Java 虚拟机原理Class 字节码二进制文件分析 六 ( 属性类型 | Code 属性 | 属性名称索引 | 属性长度 | 操作数栈最大深度 | 局部变量存储空间 | 字节码长度 )
Java 虚拟机原理动态字节码技术 | Dalvik & ART 虚拟机 | Android 字节码打包过程
Java 虚拟机原理Class 字节码二进制文件分析 五 ( 方法计数器 | 方法表 | 访问标志 | 方法名称索引 | 方法返回值类型 | 方法属性数量 | 方法属性表 )
Java 虚拟机原理Class 字节码二进制文件分析 二 ( 常量池位置 | 常量池结构 | tag | info[] | 完整分析字节码文件中的常量池二进制数据 )