Chiriri's blog Chiriri's blog
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)

Iekr

苦逼后端开发
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)
  • JavaSE

  • JavaEE

  • Linux

  • MySQL

  • NoSQL

  • Python

  • Python模块

  • 机器学习

  • 设计模式

  • 传智健康

  • 畅购商城

  • 博客项目

  • JVM

    • 字节码篇
    • 类的加载
    • 内存结构
    • 执行引擎
    • 垃圾回收
    • 字节码指令
      • Class文件结构
        • 解析方式
        • 一个个字节分析
        • javap指令
        • IDEA插件
        • 文件结构
        • 魔数
        • class文件版本
        • 常量池
        • 访问标志
        • 类索引、父类索引、接口索引集合
        • 字段表集合
        • 方法表集合
        • 属性表集合
      • 字节码指令集
  • JUC

  • Golang

  • Kubernetes

  • 硅谷课堂

  • C

  • 源码

  • 神领物流

  • RocketMQ

  • 短链平台

  • 后端
  • JVM
Iekr
2023-12-03
目录

字节码指令

# 字节码指令

# Class 文件结构

image-20231203182535230

image-20231203182539760

# 解析方式

# 一个个字节分析

使用 NotePad++ 或 Binary Viewer 等工具查看 16 进制编码

image-20231203182610332

# javap 指令

image-20231203182633173

# IDEA 插件

jclasslib 或客户端

image-20231203182649838

image-20231203182654910

image-20231203182659409

# 文件结构

类型 名称 说明 长度 数量
u4 magic 魔数,识别 Class. 文件格式 4 个字节 1
u2 minor_version 副版本号 2 个字节 1
u2 major_version 主版本号 2 个字节 1
u2 constant_pool_count 常量池计算器 2 个字节 1
cp_info constant_pool 常量池 n 个字节 constant_pool_count-1
u2 access_flags 访问标志 2 个字节 1
u2 this_class 类索引 2 个字节 1
u2 super_class 父类索引 2 个字节 1
u2 interfaces_count 接口计数器 2 个字节 1
u2 interfaces 接口索引集合 2 个字节 interfaces count
u2 fields_count 字段个数 2 个字节 1
field_info fields 字段集合 n 个字节 fields_count
u2 methods_count 方法计数器 2 个字节 1
method_info methods 方法集合 n 个字节 methods count
u2 attributes_count 附加属性计数器 2 个字节 1
attribute_info attributes 附加属性集合 n 个字节 attributes_count

即:

ClassFile {
  u4     magic;
  u2     minor_version;
  u2     major_version;
  u2     constant_pool_count ;
  cp_info   constant_pool[constant_pool_count-1];
  u2     access_flags;
  u2     this_class;
  u2     super_class;
  u2     interfaces_count;
  u2     interfaces[interfaces_count];
  u2     fields_count;
  field_info       fields[fields_count];
  u2     methods_count;
  method_info        methods[methods_count];
  u2     attributes_count;
  attribute_info  attributes[attributes_count];
} 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 魔数

Magic (魔数)

  • 每个 Class 文件的头 4 个字节称为 “魔数(Magic Number)”
  • 它的唯一作用是确定这个文件是否为一个能被虚拟机所接受的有效、合法的 class 文件。
  • class 文件的魔数值固定为 OxCAFEBABE,不会改变。

# class 文件版本

版本号

  • 排列在 magic 后的第 5 个和第 6 个字节所代表的含义就是编译的副版本号 minor_version,而第 7 个和第 8 个字节就是编译的主版本号 major_version。
  • 验证字节码文件的主版本号和次版本号同样也是格式验证的任务之一,因为如果是高版本的 JDK 编译的字节码文件,自然不能在低版本的 JVM 中运行,否则 JVM 会抛出 java.lang.UnsupportedClassVersionError 异常。

# 常量池

常量池(constant_pool)

和符号表类似,详情请看下面的 “运行时常量池”

  • constant_pool_count (常量池计数器):constant_pool_count 的值等于常量池表中的成员数加 1。常量池表的索引值只有在大于 0 且小于 constant_pool_count 时才会认为是有效的,对于 long 和 double 类型有例外情况。
  • constant_pool [](常量池):constant_pool 是一种表结构,以 1 ~ constant_pool_count - 1 为索引。它包含 class 文件结构及其子结构中引用的所有字符串常量、类或接口名、字段名和其他常量。常量池中的每一项都具备相同的特征 —— 第 1 个字节作为类型标记,用于确定该项的格式,这个字节称为 tag byte (标记字节、标签字节)。

# 访问标志

常量池后面就是访问标志,用两个字节来表示,其标识了类或者接口的访问信息,比如:该 Class 文件是类还是接口,是否被定义成 public,是否是 abstract,如果是类,是否被声明成 final 等等。各种访问标志如下所示:

标志名称 标志值 含义
ACC_PUBLIC 0x0001 是否为 Publica 类型
ACC_FINAL 0x0010 是否被声明为 final, 只有类可以设置
ACC_SUPER 0x0020 是否允许使用 invokespecial 字节码指令的新语义,JDK1.0.,2 之后编译出来的类的这个标志默认为真
ACC_INTERFACE 0x0200 标志这是一个接口
ACC_ABSTRACT 0x0400 是否为 abstracta 类型,对于接口或者抽象类来说,次标志值为真,其他类型为假
ACC _SYNTHETIC 0x1000 标志这个类并非由用户代码产生
ACC_ANNOTATION 0x2000 标志这是一个注解
ACC_ENUM ×4000 标志这是一个枚举

# 类索引、父类索引、接口索引集合

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

  • 访问标志后的两个字节就是类索引;
  • 类索引后的两个字节就是父类索引;
  • 父类索引后的两个字节则是接口索引计数器。

通过这三项,就可以确定了这个类的继承关系了。

# 字段表集合

字段表用来描述类或者接口中声明的变量。这里的字段包含了类级别变量以及实例变量,但是不包括方法内部声明的局部变量。

fields:指向常量池索引集合,它完整描述了每个字段。

  • fields_count (字段计数器):fields_count 的值表示当前 class 文件 fields 表的成员个数。fields 表中每个成员都是一个 field_info 结构,用于表示该类或接口所声明的类字段或者实例字段。
  • fields [](字段表):fields 表中的每个成员都必须是一个 fields_info 结构的数据项,用 于表示当前类或接口中某个字段的完整描述。fields 表描述当前类或接口声明的所有字段,但不包括从父类或父接口继承的那些字段。

字段表访问标志:

标志名称 标志值 含义
ACC_PUBLIC 0x0001 字段是否为 public
ACC_PRIVATE 0x0002 字段是否为 private
ACC_PROTECTED 0x0004 字段是否为 protected
ACC_STATIC 0x0008 字段是否为 static
ACC_FINAL 0x0010 字段是否为 final
ACC_VOLATILE 0x0040 字段是否为 volatile
ACC_TRANSTENT 0x0080 字段是否为 transient
ACC_SYNCHETIC 0x1000 字段是否为由编译器自动产生
ACC_ENUM 0x4000 字段是否为 enum

# 方法表集合

methods:指向常量池索引集合,它完整描述了每个方法的签名,如果这个方法不是抽象的或者不是 native 的,那么字节码中会体现出来。

  • methods_count (方法计数器):methods_count 的值表示当前 class 文件 methods 表的成员个数。methods 表中每个成员都是一个 method_info 结构。
  • methods [](方法表):methods 表中的每个成员都必须是一个 method_info 结构,用于表示当前类或接口中某个方法的完整描述。如果某个 method_info 结构的 access_ flags 项既没有设置 ACC_NATIVE 标志也没有设置 ACC_ABSTRACT 标志,那么该 结构中也应包含实现这个方法所用的 Java 虚拟机指令。

method_info 结构可以表示类和接口中定义的所有方法,包括实例方法、类方法、 实例初始化方法和类或接口初始化方法。methods 表只描述当前类或接口中声明的方法,不包括从父类或父接口继承的方法。

方法表访问标志:

标志名称 标志值 含义
ACC_PUBLIC 0x0001 方法是否为 oublic
ACC_PRIVATE 0x0002 方法是否为 private
ACC_PROTECTED 0x0004 方法是否为 protected
ACC_STATIC 0x0008 方法是否为 static
ACC_FINAL 0x0010 方法是否为 final
ACC_SYHCHRONRIZED 0x0020 方法是否为 synchronized
ACC_BRIDGE 0x0040 方法是否是有编译器产生的方法
ACC_VARARGS 0x0080 方法是否接受参数
ACC_NATIVE 0x0100 方法是否为 native
ACC_ABSTRACT 0x0400 方法是否为 abstract
ACC_STRICTFP 0x0800 方法是否为 strictfp
ACC_SYNTHETIC 0x1000 方法是否是有编泽器自动产生的

方法表结构:

类型 名称 含义 数量
u2 access_flags 访问标志 1
u2 name_index 方法名索引 1
u2 descriptor_index 描述符索引 1
u2 attributes count 属性计数器 1
attribute_info attributes 属性集合 attributes count

# 属性表集合

前面说到了属性表,现在来重点看下。属性表不仅在方法表有用到,字段表和 Class 文件中也会用得到。本篇文章中用到的例子在字段表中的属性个数为 0,所以也没涉及到;在方法表中用到了 2 次,都是 Code 属性;至于 Class 文件,在末尾时会讲到,这里就先不说了。

attributes:不同值的集合,它提供了额外的关于这个类的信息,包括任何带有 RetentionPolicy.CLASS 或者 RetentionPolicy.RUNTIME 的注解。

  • attributes_count (属性计数器):attributes_count 的值表示当前 class 文件属性表的成员个数。属性表中每一项都是一个 attribute_info 结构。
  • attributes [](属性表):属性表的每个项的值必须是 attribute_info 结构。

# 字节码指令集

见《JVM 指令手册》

编辑 (opens new window)
上次更新: 2023/12/06, 01:31:48
垃圾回收
多线程

← 垃圾回收 多线程→

最近更新
01
k8s
06-06
02
进程与线程
03-04
03
计算机操作系统概述
02-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Iekr | Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式