javap和字节码

news/2024/11/17 18:45:30/文章来源:https://www.cnblogs.com/sprinining/p/18303875

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: Iflags: (0x0002) ACC_PRIVATE// 方法表// 构造方法,返回类型为 void,访问标志为 publicpublic test.JVM.Test();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:// stack 为最大操作数栈,Java 虚拟机在运行的时候会根据这个值来分配栈帧的操作数栈深度// locals 为局部变量所需要的存储空间,单位为槽(slot),方法的参数变量和方法内的局部变量都会存储在局部变量表中;局部变量表的容量以变量槽为最小单位,一个变量槽可以存放一个 32 位以内的数据类型,比如 boolean、byte、char、short、int、float、reference 和 returnAddress 类型;局部变量表所需的容量大小是在编译期间完成计算的,大小由编译器决定;对于实例方法(如构造方法),局部变量表的第一个位置(索引 0)总是用于存储 this 引用// args_size 为方法的参数个数,有一个隐藏的 this 变量stack=2, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: bipush        107: putfield      #2                  // Field age:I10: return// 描述源码行号与字节码行号(字节码偏移量)之间的对应关系LineNumberTable:line 4: 0line 5: 4// LocalVariableTable描述帧栈中的局部变量与源码中定义的变量之间的关系LocalVariableTable:// Start 和 Length:定义变量在方法中的作用域。Start 是变量生效的字节码偏移量,Length 是它保持活动的长度。// Slot:变量在局部变量数组中的索引// Name:变量的名称,如在源代码中定义的// Signature:变量的类型描述符Start  Length  Slot  Name   Signature0      11     0  this   Ltest/JVM/Test;// 成员方法public int getAge();descriptor: ()Iflags: (0x0001) ACC_PUBLICCode:// 最大操作数栈为 1,局部变量所需要的存储空间为 1,方法的参数个数为 1,是因为局部变量只有一个隐藏的 this,并且字节码指令中只执行了一次 aload_0stack=1, locals=1, args_size=1//  加载 this 引用到栈顶,以便接下来访问实例字段 age0: aload_0// 获取字段值。这条指令读取 this 对象的 age 字段的值,并将其推送到栈顶。#2 是对常量池中的字段引用。1: getfield      #2                  // Field age:I// 返回栈顶整型值。这里返回的是 age 字段的值4: ireturnLineNumberTable:line 8: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       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

然后是字段的类型(可以是基本数据类型、数组和对象)和名称。

方法表集合

  • 方法表用来描述接口或者类中声明的方法,包括类方法和成员方法,以及构造方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/744273.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Prometheus之钉钉

要实现Prometheus通过Alertmanager发送告警到钉钉,您可以按照以下步骤进行配置:创建钉钉机器人:首先,您需要在钉钉群中添加一个自定义机器人,并获取机器人的Webhook地址。创建机器人时,您可以设置安全验证方式,如加签。创建完成后,保存好Webhook地址和加签后的秘钥(如…

Java——N以内累加求和

2024/07/15 1.题目 2.错误 3.分析 4.答案 1.题目2.错误 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int N = scanner.nextInt();int sum = 0;while (N<=1000) {for (int i=1;i<=N;…

SQLCoder部署和应用

SQLCoder文生SQL部署和应用主页个人微信公众号:密码应用技术实战 个人博客园首页:https://www.cnblogs.com/informatics/SQLCoder简介 SQLCoder是一个用于生成SQL语句的工具,可以通过输入自然语言描述的需求,生成对应的SQL语句。SQLCoder支持连接数据库,对生成的SQL语句可…

NOIP 十三连测 #2 补题

逆天输出文件 .ans reverse 水题,随便自己造两组数据都能看出规律: \[\begin{cases}a_n a_{n - 2} \dots a_1 + a_2 a_4 \dots a_{n - 1}(n \mod 2 = 1) \\ a_n a_{n - 2} \dots a_2 + a_1 a_3 \dots a_{n - 1 } (n \mod 2 = 0)\end{cases} \]logistics 先求出最小生成树的 \…

MySQL时间戳转成日期格式

将时间戳转换为日期格式:-- 如果时间戳为毫秒级长度为13位,需要先除以1000 SELECT id, `task_name` ,FROM_UNIXTIME(`task_register_begin_time`/1000,%Y-%m-%d %H:%i:%s) as task_register_begin_time,FROM_UNIXTIME(`task_register_end_time`/1000,%Y-%m-%d %H:%i:%s) as t…

使用GSAP制作动画视频

GSAP 3Blue1Brown给我留下了深刻印象。利用动画制作视频,内容简洁,演示清晰。前两天刚好碰到一件事,我就顺便学习了一下怎么用代码做动画。 以javascrip为例,有两个动画引擎,GSAP和Animajs。由于网速的原因,询问了GPT后,我选择了GSAP来制作我的第一个动画视频。 制作动画…

log4cpp的安装及使用

介绍开源库log4cpp的安装及使用目录前言安装使用示例代码配置文件编译链接输出 前言 本文的操作均在ubuntu20.04下进行 安装 本文仅介绍从源码编译安装log4cpp的过程。 ①在开始编译前,首先要确保系统中安装了g++,make,autoconf和libtool ②下载log4cpp源码 下载log4cpp的特…

Intellij springboot远程调试

服务器端配置: java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005 XXXX.jar 说明: address:IP:端口;*代表所有IP地址都可访问,5005需要可IDEA远程请求的端口一致 XXXX.jar:你的springboot程序 IDEA端配置:

采购订单列表根据多条件设置单元格背景色

bos配置: 如果值存在空字符串和空格,空格会标红,为空不会。因此单独针对空字符串标红。 测试效果:

面试准备【LLM】

目录其他注意力过拟合的表现有哪些?BN 训练和测试的区别在哪里?梯度下降的公式?反向传播优化器 & Adam均方误差损失交叉熵损失梯度消失问题梯度爆炸问题权重正则化过拟合分词器BERT掩码语言建模 (MLM)下一个句子预测 Next Sentence Prediction(NSP)BERT微调BERT模型创新…

帝国CMS网站为什么发布时间比实际时间相差8个小时?

你的php设置的时间有问题,是美国的时间。有以下两种方法可解决:1、修改php.ini,找到:date.timezone,把前面的分号去掉,并把值设为PRC2、修改e/class/config.php文件,把://@date_default_timezone_set("PRC");前面的//去掉即可本文来自博客园,作者:黄文Rex,…

易优CMS英文名称设置与调用标签

{$field.englist_name}本文来自博客园,作者:黄文Rex,转载请注明原文链接:https://www.cnblogs.com/hwrex/p/18303796