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和字节码的更多相关文章

  1. 001-Eclipse、idea集成javap查看字节码、javap说明

    一.概述 分析java语言特性的一个好帮手是使用javap工具查看java编译后的字节码,如何在eclipse中配置javap工具快速查看java字节码. 二.Eclipse集成javap查看字节码 ...

  2. Eclipse集成javap查看字节码

    分析java语言特性的一个好帮手是使用javap工具查看java编译后的字节码,楼主今天在学习java泛型中的桥方法时遇到一些不解,想到javap这个好工具可以帮助解答一些疑惑,索性就捣鼓如何在ecl ...

  3. Javap -c 字节码解析

              栈和局部变量操作 将常量压入栈的指令 aconst_null         将null对象引用压入栈   iconst_m1         将int类型常量-1压入栈 icon ...

  4. javap -c 字节码含义

    aconst_null         将null对象引用压入栈 iconst_m1         将int类型常量-1压入栈 iconst_0         将int类型常量0压入栈 icons ...

  5. 命令查看java的class字节码文件、verbose、synchronize、javac、javap

    查看Java字节码 1 javac –verbose查看运行类是加载了那些jar文件 HelloWorld演示: public class Test { public static void main ...

  6. Java Class 字节码文件结构详解

    Class字节码中有两种数据类型: 字节数据直接量:这是基本的数据类型.共细分为u1.u2.u4.u8四种,分别代表连续的1个字节.2个字节.4个字节.8个字节组成的整体数据. 表:表是由多个基本数据 ...

  7. 命令查看java的class字节码文件

    源代码: public class Math { public static void main(String[] args){ int a=1; int b=2; int c=(a+b)*10; } ...

  8. java字节码速查笔记

    java字节码速查笔记  发表于 2018-01-27 |  阅读次数: 0 |  字数统计: |  阅读时长 ≍ 执行原理 java文件到通过编译器编译成java字节码文件(也就是.class文件) ...

  9. Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)

    前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...

  10. @使用javap反编译Java字节码文件

    在Sun公司提供的JDK中,就已经内置了Java字节码文件反编译工具javap.exe(位于JDK安装目录的bin文件夹下). 我们可以在dos窗口中使用javap来反汇编指定的Java字节码文件.在 ...

随机推荐

  1. java多线程之-线程池状态

    1.背景 这一节我们来学习一下线程池状态..... 2.线程池状态 状态名称 高3位 是否接受新任务 是否处理队列中的任务 说明 RUNNING 111 是 是 线程池正常运行状态 SHUTDOWN ...

  2. 解决 jquery attr多次使用失效的问题

    今天做一个全选功能的时候用到了jq 的attr 的方法,可是在真正使用的时候首次是可以实现全选和全不选的功能,然而 多点几次就会发勾选的效果消失了!先看下代码吧: <!DOCTYPE html& ...

  3. 洛谷P5250 【深基17.例5】木材仓库

    [深基17.例5]木材仓库 题目描述 博艾市有一个木材仓库,里面可以存储各种长度的木材,但是保证没有两个木材的长度是相同的.作为仓库负责人,你有时候会进货,有时候会出货,因此需要维护这个库存.有不超过 ...

  4. Sentry 产品指南文档(附:详细脑图整理)

    Sentry 基础知识 https://docs.sentry.io/product/ https://docs.sentry.io/product/sentry-basics/ 问题 https:/ ...

  5. SMU Summer 2024 Contest Round 6

    SMU Summer 2024 Contest Round 6 Many Formulas 题意 给你一个数,你可以在这个数的任意位之间插入零个或多个+号,形成一个算式,你需要计算所有可能形成的算式的 ...

  6. 学习SSD—day1_20240814

    1.SSD的基本概念以及结构 SSD是一种以半导体(半导体闪存)作为存储介质吗,使用纯电子电路实现的存储设备. SSD硬件包括几大组成部分:主控.闪存.缓存芯片DRAM(可选,有些SSD上可能只有SR ...

  7. C语言的指定初始化

    ----------------版权声明:本文为CSDN博主「Supan-Yang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog ...

  8. 需要多久才能看完linux内核源码?

    代码中自由颜如玉!代码中自有黄金屋! 一.内核行数 Linux内核分为CPU调度.内存管理.网络和存储四大子系统,针对硬件的驱动成百上千.代码的数量更是大的惊人. 先说说最早的内核linux 0.11 ...

  9. GC终结标记 SuspendEE 是怎么回事

    一:背景 1. 讲故事 写这篇是起源于训练营里有位朋友提到了一个问题,在 !t -special 输出中有一个 SuspendEE 字样,这个字样在 coreclr 中怎么弄的?输出如下: 0:000 ...

  10. 【FFmpeg】之Mac系统爬取所有M3U8视频下载方法

    前言 由于有的网站不允许下载视频,到了有效期就不能看了,但是我想以后反复看,怎么办呢? 前提准备 操作系统:Mac 浏览器:谷歌浏览器 抓取m3u8工具:猫爪 视频处理工具:ffmpeg 需要安装工具 ...