javap和字节码
javap

字节码的基本信息
public class Test {
private int age = 10;
public int getAge() {
return age;
}
}
- 在 class 文件的同级目录下输入命令
javap -v -p Test.class来查看一下输出的内容
// 字节码文件的位置
Classfile /D:/Code/code/JavaCode/JavaSourceLearn/out/production/JavaSourceLearn/test/JVM/Test.class
// 文件的修改日期和大小
Last modified 2024年7月15日; size 369 bytes
// 字节码文件的 SHA-256 值,用于校验文件的完整性
SHA-256 checksum ece86f04e47d4ba3e27fc08cf3cb675a31670d9eab284fc0b2e8487ed8ed1c73
// 该字节码文件编译自 Main.java 源文件
Compiled from "Test.java"
// 类访问修饰符和类型,表明这是一个公开的类,名为test.JVM.Test
public class test.JVM.Test
// 次版本号
minor version: 0
// 主版本号 由 Java 8 编译
major version: 52
// 类访问标记:表明当前类是 ACC_PUBLIC | ACC_SUPER(表明这个类是 public 的,并且使用了 super 关键字)。
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
// 当前类的索引,指向常量池中下标为 3 的常量,当前类是 Test 类
this_class: #3 // test/JVM/Test
// 父类的索引,指向常量池中下标为 4 的常量,当前类的父类是 Object 类
super_class: #4 // java/lang/Object
// 当前类有 0 个接口,1 个字段(age),2 个方法(getAge()方法和缺省的默认构造方法),1 个属性(该类仅有的一个属性是 SourceFIle,包含了源码文件的信息)。
interfaces: 0, fields: 1, methods: 2, attributes: 1
// 常量池
Constant pool:
// 类型为 Methodref,表明是用来定义方法的,指向常量池中下标为 4 和 18 的常量
#1 = Methodref #4.#18 // java/lang/Object."<init>":()V
// 类型为 Fieldref,表明是用来定义字段的,指向常量池中下标为 3 和 19 的常量
#2 = Fieldref #3.#19 // test/JVM/Test.age:I
// 类型为 Class,表明是用来定义类(或者接口)的,指向常量池中下标为 20 的常量
#3 = Class #20 // test/JVM/Test
// 类型为 Class,表明是用来定义类(或者接口)的,指向常量池中下标为 21 的常量
#4 = Class #21 // java/lang/Object
// 类型为 Utf8,UTF-8 编码的字符串,值为 age,表明字段名为 age
#5 = Utf8 age
// 类型为 Utf8,UTF-8 编码的字符串,值为 I,表明字段的类型为 int
#6 = Utf8 I
// 类型为 Utf8,UTF-8 编码的字符串,值为 <init>,表明为构造方法
#7 = Utf8 <init>
// 类型为 Utf8,UTF-8 编码的字符串,值为 ()V,表明方法的返回值为 void
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Ltest/JVM/Test;
#14 = Utf8 getAge
#15 = Utf8 ()I
#16 = Utf8 SourceFile
#17 = Utf8 Test.java
// 类型为 NameAndType,表明是字段或者方法的部分符号引用,指向常量池中下标为 7 和 8 的常量
#18 = NameAndType #7:#8 // "<init>":()V
// 类型为 NameAndType,表明是字段或者方法的部分符号引用,指向常量池中下标为 5 和 6 的常量
#19 = NameAndType #5:#6 // age:I
#20 = Utf8 test/JVM/Test
// 类型为 Utf8,UTF-8 编码的字符串,值为 java/lang/Object
#21 = Utf8 java/lang/Object
{
// 字段表
private int age;
descriptor: I
flags: (0x0002) ACC_PRIVATE
// 方法表
// 构造方法,返回类型为 void,访问标志为 public
public test.JVM.Test();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
// stack 为最大操作数栈,Java 虚拟机在运行的时候会根据这个值来分配栈帧的操作数栈深度
// locals 为局部变量所需要的存储空间,单位为槽(slot),方法的参数变量和方法内的局部变量都会存储在局部变量表中;局部变量表的容量以变量槽为最小单位,一个变量槽可以存放一个 32 位以内的数据类型,比如 boolean、byte、char、short、int、float、reference 和 returnAddress 类型;局部变量表所需的容量大小是在编译期间完成计算的,大小由编译器决定;对于实例方法(如构造方法),局部变量表的第一个位置(索引 0)总是用于存储 this 引用
// args_size 为方法的参数个数,有一个隐藏的 this 变量
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 10
7: putfield #2 // Field age:I
10: return
// 描述源码行号与字节码行号(字节码偏移量)之间的对应关系
LineNumberTable:
line 4: 0
line 5: 4
// LocalVariableTable描述帧栈中的局部变量与源码中定义的变量之间的关系
LocalVariableTable:
// Start 和 Length:定义变量在方法中的作用域。Start 是变量生效的字节码偏移量,Length 是它保持活动的长度。
// Slot:变量在局部变量数组中的索引
// Name:变量的名称,如在源代码中定义的
// Signature:变量的类型描述符
Start Length Slot Name Signature
0 11 0 this Ltest/JVM/Test;
// 成员方法
public int getAge();
descriptor: ()I
flags: (0x0001) ACC_PUBLIC
Code:
// 最大操作数栈为 1,局部变量所需要的存储空间为 1,方法的参数个数为 1,是因为局部变量只有一个隐藏的 this,并且字节码指令中只执行了一次 aload_0
stack=1, locals=1, args_size=1
// 加载 this 引用到栈顶,以便接下来访问实例字段 age
0: aload_0
// 获取字段值。这条指令读取 this 对象的 age 字段的值,并将其推送到栈顶。#2 是对常量池中的字段引用。
1: getfield #2 // Field age:I
// 返回栈顶整型值。这里返回的是 age 字段的值
4: ireturn
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ltest/JVM/Test;
}
SourceFile: "Test.java"
Java 虚拟机是在加载字节码文件的时候才进行的动态链接,也就是说,字段和方法的符号引用只有经过运行期转换后才能获得真正的内存地址。当 Java 虚拟机运行时,需要从常量池获取对应的符号引用,然后在类创建或者运行时解析并翻译到具体的内存地址上。
Test类使用的是默认的构造方法,来源于 Object 类。
#4指向Class #21(即java/lang/Object),#18指向NameAndType #7:#8(即<init>:()V)。声明了一个类型为 int 的字段 age。
#3指向Class #20(即test/JVM/Test),#19指向NameAndType #5:#6(即age:I)
| 标识字符 | 含义 |
|---|---|
| B | 基本数据类型 byte |
| C | 基本数据类型 char |
| D | 基本数据类型 double |
| F | 基本数据类型 float |
| I | 基本数据类型 int |
| J | 基本数据类型 long |
| S | 基本数据类型 short |
| Z | 基本数据类型 boolean |
| V | 特殊类型 void |
| L | 引用数据类型,以分号“;”结尾 |
| [ | 一维数组 |
字段表集合
- 字段表用来描述接口或者类中声明的变量,包括类变量和成员变量,但不包含声明在方法中局部变量
字段的修饰符一般有:
- 访问权限修饰符,比如 public private protected
- 静态变量修饰符,比如 static
- final
- 并发可见性修饰符,比如 volatil序列化修饰符,比如 transient
然后是字段的类型(可以是基本数据类型、数组和对象)和名称。
方法表集合
- 方法表用来描述接口或者类中声明的方法,包括类方法和成员方法,以及构造方法
javap和字节码的更多相关文章
- 001-Eclipse、idea集成javap查看字节码、javap说明
一.概述 分析java语言特性的一个好帮手是使用javap工具查看java编译后的字节码,如何在eclipse中配置javap工具快速查看java字节码. 二.Eclipse集成javap查看字节码 ...
- Eclipse集成javap查看字节码
分析java语言特性的一个好帮手是使用javap工具查看java编译后的字节码,楼主今天在学习java泛型中的桥方法时遇到一些不解,想到javap这个好工具可以帮助解答一些疑惑,索性就捣鼓如何在ecl ...
- Javap -c 字节码解析
栈和局部变量操作 将常量压入栈的指令 aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 icon ...
- javap -c 字节码含义
aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 iconst_0 将int类型常量0压入栈 icons ...
- 命令查看java的class字节码文件、verbose、synchronize、javac、javap
查看Java字节码 1 javac –verbose查看运行类是加载了那些jar文件 HelloWorld演示: public class Test { public static void main ...
- Java Class 字节码文件结构详解
Class字节码中有两种数据类型: 字节数据直接量:这是基本的数据类型.共细分为u1.u2.u4.u8四种,分别代表连续的1个字节.2个字节.4个字节.8个字节组成的整体数据. 表:表是由多个基本数据 ...
- 命令查看java的class字节码文件
源代码: public class Math { public static void main(String[] args){ int a=1; int b=2; int c=(a+b)*10; } ...
- java字节码速查笔记
java字节码速查笔记 发表于 2018-01-27 | 阅读次数: 0 | 字数统计: | 阅读时长 ≍ 执行原理 java文件到通过编译器编译成java字节码文件(也就是.class文件) ...
- Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)
前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...
- @使用javap反编译Java字节码文件
在Sun公司提供的JDK中,就已经内置了Java字节码文件反编译工具javap.exe(位于JDK安装目录的bin文件夹下). 我们可以在dos窗口中使用javap来反汇编指定的Java字节码文件.在 ...
随机推荐
- 关于“内网穿透”的一些知识(续3)—— NAT类型判断
前文: 关于"内网穿透"的一些知识(续2)-- 端口预测 ------------------------------------------- 本文是对前面几篇文章的补充.这里要 ...
- win10系统wifi不会自动连接怎么解决
参考: https://jingyan.baidu.com/article/d621e8da743bab2865913f99.html ================================ ...
- vscode下如何把缩进为2个空格的python项目改为4个空格的缩进
最近在看老项目的代码,是python2.7年代的项目,那个时候很多的python项目都是使用2个空格,不过现在估计大多数人写python项目都是使用4个空格的了,而我看这两个空格的项目代码也是感觉十分 ...
- vue之父组件与子组件
1.背景 2.简单使用 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- ×被替换成x 的解决办法
今天写代码遇到一个很有趣的问题: 在php中使用echo 输出url的时候当url中包含×字段时就会被html直接解析成 x (乘号)这样一来我返回的地址就不能正常访问url了: 解 ...
- 精读代码,实战进阶&实践Task2
背景 从零入门AI生图原理&实践 是 Datawhale 2024 年 AI 夏令营第四期的学习活动("AIGC"方向),基于魔搭社区"可图Kolors-LoRA ...
- 使用image-syncer镜像同步工具将阿里云镜像仓库镜像迁移至私有Harbor
借助于阿里云开源的镜像同步工具image-syncer实现harbor及阿里云镜像仓库之间的镜像迁移 下载镜像同步工具 curl -fL "https://wiseo-generic.pkg ...
- zabbix 4.0监控web页面
web监控 web监测是用来监控web程序的,可以监控web程序的平均下载速度.响应时间.HTTP状态码. 环境 至少有两台被监控主机 静态网页检测 选择监控主机 配置场景 web监测->创 ...
- GNU make-Makefile文件简介
Makefile简介 Makefile是一种特殊格式的文件,被make工具使用来管理软件的构建过程.Makefile定义了一组规则和依赖关系,告诉make如何编译和链接程序. Makefile语句 T ...
- Ruby 学习笔记
基本语法 变量 name = "Alice" age = 30 puts "Name: #{name}, Age: #{age}" var # 局部变量 @va ...