IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> 使用javap指令解析Class文件 -> 正文阅读

[开发工具]使用javap指令解析Class文件

接卸字节码的作用

通过反编译生成的字节码文件,我们可以深入的了解Java代码的工作机制。但是,自己分析类文件结构太麻烦了!除了使用第三方的jclasslib工具之外,oracle官方也提供了工具:javap。

javap是jdk自带的反解析工具。它的作用就是根据class字节码文件,反解析出当前类对应的code区、局部变量表、异常表和代码行偏移量映射表、常量池等信息。

通过局部变量表,我们可以产看局部变量的作用域范围、所在槽位等信息,甚至可以看到槽位复用等信息。

javac -g 操作

解析字节码文件得到的信息中,有些信息(如局部变量表、指令和代码行偏移量映射表、常量池中方法的参数名称等等)需要在使用javac编译成class文件时,指定参数才能输出。

比如,直接javac xx.java,就不会生成对应的局部变量表等信息,如果你使用javac -g xx.java就可以生成所有相关信息了。如果你使用的eclipse或者IDEA,则默认情况下,eclipse、IDEA在编译时会帮你生成局部变量表、指令和代码行偏移量映射表等信息。

javap的用法

javap的用法格式:

javap <options> <classes>

其中,classes就是要反编译的class文件。
在命令行中直接输入javap或javap -help可以看到javap的options选项:

Usage: javap <options> <classes>
where possible options include:
  -help  --help  -?        Print this usage message
  -version                 Version information
  -v  -verbose             Print additional information
  -l                       Print line number and local variable tables
  -public                  Show only public classes and members
  -protected               Show protected/public classes and members
  -package                 Show package/protected/public classes
                           and members (default)
  -p  -private             Show all classes and members
  -c                       Disassemble the code
  -s                       Print internal type signatures
  -sysinfo                 Show system info (path, size, date, MD5 hash)
                           of class being processed
  -constants               Show final constants
  -classpath <path>        Specify where to find user class files
  -cp <path>               Specify where to find user class files
  -bootclasspath <path>    Override location of bootstrap class files

使用举例

1.代码

package com.example.jvm;

public class SeniorDemo {

    private int num = 1;
    public final String info = "hello world";
    boolean[] counts;

    public SeniorDemo() {

    }

    public SeniorDemo(int count) {
        this.counts = new boolean[count];
    }

    public String getInfo() {
        return info;
    }

    public void addNum(int n) {
        num += n;
        System.out.println(num);
    }
}
  1. javap -v SeniorDemo.class
Classfile /home/mall/work/gitrepository/jvm/out/production/jvm/SeniorDemo.class
  Last modified Nov 11, 2021; size 852 bytes
  MD5 checksum 0d32355daa6291e418aba33a4302a55d
  Compiled from "SeniorDemo.java"
public class SeniorDemo  // 类名称
  minor version: 0
  major version: 52    // 主版本号和副版本号组合,得出编译该文件的jdk版本
  flags: ACC_PUBLIC, ACC_SUPER // 方法标识
#####################################常量池开始########################################
Constant pool: 
   #1 = Methodref          #9.#32         // java/lang/Object."<init>":()V
   #2 = Fieldref           #6.#33         // SeniorDemo.num:I
   #3 = String             #34            // hello world
   #4 = Fieldref           #6.#35         // SeniorDemo.info:Ljava/lang/String;
   #5 = Fieldref           #6.#36         // SeniorDemo.counts:[Z
   #6 = Class              #37            // SeniorDemo
   #7 = Fieldref           #38.#39        // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Methodref          #40.#41        // java/io/PrintStream.println:(I)V
   #9 = Class              #42            // java/lang/Object
  #10 = Utf8               num
  #11 = Utf8               I
  #12 = Utf8               info
  #13 = Utf8               Ljava/lang/String;
  #14 = Utf8               ConstantValue
  #15 = Utf8               counts
  #16 = Utf8               [Z
  #17 = Utf8               <init>
  #18 = Utf8               ()V
  #19 = Utf8               Code
  #20 = Utf8               LineNumberTable
  #21 = Utf8               LocalVariableTable
  #22 = Utf8               this
  #23 = Utf8               LSeniorDemo;
  #24 = Utf8               (I)V
  #25 = Utf8               count
  #26 = Utf8               getInfo
  #27 = Utf8               ()Ljava/lang/String;
  #28 = Utf8               addNum
  #29 = Utf8               n
  #30 = Utf8               SourceFile
  #31 = Utf8               SeniorDemo.java
  #32 = NameAndType        #17:#18        // "<init>":()V
  #33 = NameAndType        #10:#11        // num:I
  #34 = Utf8               hello world
  #35 = NameAndType        #12:#13        // info:Ljava/lang/String;
  #36 = NameAndType        #15:#16        // counts:[Z
  #37 = Utf8               SeniorDemo
  #38 = Class              #43            // java/lang/System
  #39 = NameAndType        #44:#45        // out:Ljava/io/PrintStream;
  #40 = Class              #46            // java/io/PrintStream
  #41 = NameAndType        #47:#24        // println:(I)V
  #42 = Utf8               java/lang/Object
  #43 = Utf8               java/lang/System
  #44 = Utf8               out
  #45 = Utf8               Ljava/io/PrintStream;
  #46 = Utf8               java/io/PrintStream
  #47 = Utf8               println
#####################################常量池结束########################################
#####################################字段表开始########################################
{
  public final java.lang.String info;
    descriptor: Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_FINAL
    ConstantValue: String hello world

  boolean[] counts;
    descriptor: [Z
    flags:
#####################################字段表结束########################################

#####################################方法表开始########################################
  public SeniorDemo();
    descriptor: ()V
    flags: 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: iconst_1
         6: putfield      #2                  // Field num:I
         9: aload_0
        10: ldc           #3                  // String hello world
        12: putfield      #4                  // Field info:Ljava/lang/String;
        15: return
      LineNumberTable:  // 行号表,代码行号与上面的code中的行号的对应
        line 7: 0  
        line 3: 4
        line 4: 9
        line 9: 15
      LocalVariableTable:  // 局部变量表,start标识局部变量的开始作用域,与code中的相对于
        Start  Length  Slot  Name   Signature
            0      16     0  this   LSeniorDemo; // 表明了作用域,变量名称,变量类型,也能看出槽位有没有被覆用的情况

  public SeniorDemo(int);
    descriptor: (I)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_1
         6: putfield      #2                  // Field num:I
         9: aload_0
        10: ldc           #3                  // String hello world
        12: putfield      #4                  // Field info:Ljava/lang/String;
        15: aload_0
        16: iload_1
        17: newarray       boolean
        19: putfield      #5                  // Field counts:[Z
        22: return
      LineNumberTable:
        line 11: 0
        line 3: 4
        line 4: 9
        line 12: 15
        line 13: 22
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      23     0  this   LSeniorDemo;
            0      23     1 count   I

  public java.lang.String getInfo();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: ldc           #3                  // String hello world
         2: areturn
      LineNumberTable:
        line 16: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       3     0  this   LSeniorDemo;

  public void addNum(int);
    descriptor: (I)V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_0
         1: dup
         2: getfield      #2                  // Field num:I
         5: iload_1
         6: iadd
         7: putfield      #2                  // Field num:I
        10: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        13: aload_0
        14: getfield      #2                  // Field num:I
        17: invokevirtual #8                  // Method java/io/PrintStream.println:(I)V
        20: return
      LineNumberTable:
        line 20: 0
        line 21: 10
        line 22: 20
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      21     0  this   LSeniorDemo;
            0      21     1     n   I
#####################################方法表结束########################################
}
#####################################属性开始########################################
SourceFile: "SeniorDemo.java"  // 表明类源文件的名称
#####################################属性结束########################################

总结

  1. 通过javap命令可以查看一共java类反汇编得到的Class文件版本号、常量池、访问标识、变量表、指令代码行号表等信息。不显式类索引、父类索引、接口类索引集合、<clinit>()、<init>等结构。
  2. 通过对前面例子代码反汇编文件的简单分析,可以发现,一个方法的执行通常会涉及下面几块内存的操作:
    1. java栈中,局部变量表、操作数栈
    2. java堆中,通过对象的地址引用去操作
    3. 常量池
    4. 其他如帧数据区、方法区的剩余部分等情况。
  3. 平时,我们比较关注的是java类中每个方法的反汇编中的指令操作过程,这些指令都是顺序执行的,可以参考官方文档查看每个指令的含义。
  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-11-12 19:48:05  更:2021-11-12 19:48:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:48:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码