首页
首页 教程 派聪明
  • 首页
  • 教程
  • 派聪明
  • 登录
登录技术派畅享更多权益

用户名密码登录

其他登录:
icon_GitHubCreated with sketchtool.
绑定星球,畅享VIP服务

微信扫码/长按识别登录

输入验证码
有效期五分钟 👉 手动刷新

登录即同意 用户协议 和 隐私政策

绑定二哥编程星球,畅享 VIP 尊享服务!

戳我了解如何获取星球编号,新窗口打开

添加二哥微信 itwanger 审核更快

记得备注 星球编号
我会根据星球编号进行审核
1
大白话带你认识JVM
更新时间: 2024年01月16日
星球
2
JVM是如何运行Java代码的?
更新时间: 2024年01月16日
星球
3
Java的类加载机制
更新时间: 2024年01月16日
星球
4
Java的类文件结构
更新时间: 2024年01月16日
星球
5
从javap的角度轻松看懂字节码
更新时间: 2024年01月16日
星球
6
栈虚拟机与寄存器虚拟机
更新时间: 2024年01月16日
星球
7
字节码指令详解
更新时间: 2024年01月16日
星球
8
深入理解JVM的栈帧结构
更新时间: 2024年01月16日
星球
9
深入理解JVM的运行时数据区
更新时间: 2024年01月16日
星球
10
深入理解JVM的垃圾回收机制
更新时间: 2024年01月16日
星球
11
深入理解 JVM 的垃圾收集器
更新时间: 2024年01月16日
星球
12
Java 创建的对象到底放在哪?
更新时间: 2024年01月16日
星球
13
深入理解JIT(即时编译)
更新时间: 2024年01月16日
星球
14
JVM 性能监控之命令行篇
更新时间: 2024年01月16日
星球
15
JVM 性能监控之可视化篇
更新时间: 2024年01月16日
星球
16
阿里开源的 Java 诊断神器 Arthas
更新时间: 2024年01月16日
星球
17
内存溢出排查优化实战
更新时间: 2024年01月16日
星球
18
CPU 100% 排查优化实践
更新时间: 2024年01月16日
星球
19
JVM 核心知识点总结
更新时间: 2024年01月16日
星球
20
K个一组翻转链表
更新时间: 2024年02月07日
星球
关注公众号
原创
第五节:javap 与字节码

计算机比较“傻”,只认 0 和 1,这意味着我们编写的代码最终都要编译成机器码才能被计算机执行。Java 在诞生之初就提出了一个非常著名的宣传口号: "一次编写,处处运行"。

Write Once, Run Anywhere.

为了这个口号,Java 的亲妈 Sun 公司以及其他虚拟机提供商发布了许多可以在不同平台上运行的 Java 虚拟机,而这些虚拟机都拥有一个共同的功能,那就是可以载入和执行同一种与平台无关的字节码(Byte Code)。

(前面其实我们也讲过,但为了这篇内容的完整性,我们简单过一下,这一节我们的重点是通过 javap 这个命令来了解字节码)

有了 Java 虚拟机的帮助,我们编写的 Java 源代码不必再根据不同平台编译成对应的机器码了,只需要生成一份字节码,然后再将字节码文件交由运行在不同平台上的 Java 虚拟机读取后执行就可以了。

如今的 Java 虚拟机非常强大,不仅支持 Java 语言,还支持很多其他的编程语言,比如说 Groovy、Scala、Koltin 等等。

来看一段代码吧。

public class Main {
    private int age = 18;
    public int getAge() {
        return age;
    }
}

编译生成 Main.class 文件后,可以在命令行使用 xxd Main.class 打开 class 文件(前面我们已经讲过了,还不会用的同学可以回头看一眼)。

对于这些 16 进制内容,除了开头的 cafe babe,剩下的内容大致可以翻译成:啥玩意啊这......

但经过上一节类文件结构的洗礼,相信大家对这份文件的内容已经很熟悉了。

javap

Java 内置了一个反编译命令 javap,可以通过 javap -help 了解 javap 的基本用法。

当然了,执行这个命令的前提条件是你需要配置好 Java 环境变量,如果没有配置好,可以参考这篇文章。

javap 是 JDK 自带的一个命令行工具,主要用于反编译类文件(.class 文件)。我本机是 macOS,使用了 jenv 来管理的 JDK 版本,所以看到的位置如下图所示。

Windows 用户以及没有使用 jenv 的 macOS 用户可以根据这个帖子了解 jenv,真的好用。

javap 主要用于反编译 Java 类文件,即将编译后的 .class 文件转换回更易于理解的形式。虽然它不会生成原始的 Java 源代码,但它可以显示类的结构,包括构造方法、方法、字段等,帮助我们更好地理解 Java 字节码以及 Java 程序的运行机制。

前面我们已经写了一个简单的类,大家应该还记得:

public class Main {
    private int age = 18;
    public int getAge() {
        return age;
    }
}

当然了,我希望你是用 Intellij IDEA 来编写而不是记事本,这样就省去了我们主动编译的过程,可以直接在 target 目录下找到 class 文件,这些知识我们前面都已经讲过了。

OK,我们在 class 文件的同级目录下输入命令 javap -v -p Main.class 来查看一下输出的内容(-v 显示附加信息,如局部变量表、操作码等;-p 显示所有类和成员,包括私有的,不懂的同学可以回头看在看一眼 javap -help 的输出结果 😁)。

Classfile /Users/maweiqing/Documents/GitHub/TechSisterLearnJava/codes/TechSister/target/classes/com/itwanger/jvm/Main.class
  Last modified 2021年4月15日; size 385 bytes
  SHA-256 checksum 6688843e4f70ae8d83040dc7c8e2dd3694bf10ba7c518a6ea9b88b318a8967c6
  Compiled from "Main.java"
public class com.itwanger.jvm.Main
  minor version: 0
  major version: 55
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #3                          // com/itwanger/jvm/Main
  super_class: #4                         // java/lang/Object
  interfaces: 0, fields: 1, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #4.#18         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#19         // com/itwanger/jvm/Main.age:I
   #3 = Class              #20            // com/itwanger/jvm/Main
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               age
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/itwanger/jvm/Main;
  #14 = Utf8               getAge
  #15 = Utf8               ()I
  #16 = Utf8               SourceFile
  #17 = Utf8               Main.java
  #18 = NameAndType        #7:#8          // "<init>":()V
  #19 = NameAndType        #5:#6          // age:I
  #20 = Utf8               com/itwanger/jvm/Main
  #21 = Utf8               java/lang/Object
{
  private int age;
    descriptor: I
    flags: (0x0002) ACC_PRIVATE

  public com.itwanger.jvm.Main();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: bipush        18
         7: putfield      #2                  // Field age:I
        10: return
      LineNumberTable:
        line 6: 0
        line 7: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   Lcom/itwanger/jvm/Main;

  public int getAge();
    descriptor: ()I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield  

已加入二哥编程星球,即刻绑定星球编号解锁🔐

该文档仅「二哥编程星球」的VIP用户可见

二哥的编程星球内容包括:

1. 付费文档: 技术派、MYDB 等项目配套的 120+篇教程查看权限

2. 面试指南: 校招、社招的 40 万+字面试求职攻略

3. 智能助手: 无限期使用派聪明 AI 助手,已对接讯飞星火和 ChatGPT双通道,不用花 1 分钱

4. 专属问答: 向二哥 1v1 发起提问,内容不限于 offer 选择、学习路线、职业规划等

5. 简历修改: 提供简历修改服务,附赠星球 100+优质简历模板可供参考

6. 学习环境: 打造一个沉浸式的学习环境,有一种高考冲刺、大学考研的氛围


二哥的星球

》步骤①:微信扫描上方二维码,点击「加入知识星球」按钮

》步骤②:访问星球置顶帖球友必看: https://t.zsxq.com/11rEo9Pdu,获取项目配套文档的语雀访问地址和密码

已加入星球,绑定星球编号
删除提醒

确定删除《第五节:javap 与字节码》吗

真诚点赞 诚不我欺

回复