使用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
其中,classes就是你要反编译的class文件。
在命令行中直接输入javap或javap -help可 以看到javap的options有如下选项:

这里重组一下:

  -help  --help  -?        输出此用法消息-version                 版本信息-public                  仅显示公共类和成员-protected               显示受保护的/公共类和成员-p  -private             显示所有类和成员-package                 显示程序包/受保护的/公共类和成员(默认)-sysinfo                 显示正在处理的类的系统信息(路径,大小,日期,MD5 散列)-constants               显示最终常量-s                       输出内部类型签名-l                       输出行号和本地变量表-c                       对代码进行反汇编-v  -verbose             输出附加信息-classpath <path>        指定查找用户类文件的位置-bootclasspath <path>    覆盖引导类文件的位置

一般常用的是-v -l -c三个选项。
javap -l 会输出行号和本地变量表信息。
javap -c 会对当前class字节码进行反编译生成汇编代码。
javap -v classxx 除了包含-c内容外,还会输出行号、局部变量表信息、常量池等信息。

注意:

  • -v相当于-c -l
  • -v也不会输出私有的字段、方法等信息,所以如果想输出私有的信息,那需要在-v后面加上-p才行

使用举例

代码

public class JavapTest {
private int num;
boolean flag;
protected char gender;
public String info;public static final int *COUNTS* = 1;
static {String url = "www.baidu.com";}{
info = "java";}
public JavapTest() {}
private JavapTest(boolean falg) {
this.flag = flag;}
private void methodPrivate() {}
int getNum(int i) {
return num + i;}
protected char showGender() {
return gender;}
public void showInfo() {
int i = 100;System.out.println(info + i);}
}

字节码文件分析

Classfile /C:/......./JavapTest.class   // 字节码文件所属的路径Last modified 2021-2-24; size 1393 bytes   // 最后修改时间,字节码文件的大小MD5 checksum 2c764244fa3a95bfb346c9e416a7a3f6   // MD5散列值Compiled from "JavapTest.java"   // 源文件的名称
public class io.test.JavapTestminor version: 0   // 副版本major version: 52   // 主版本flags: ACC_PUBLIC, ACC_SUPER   // 访问标识
*************************** 常量池********************************
Constant pool:#1 = Methodref          #16.#48        // java/lang/Object."":()V#2 = String             #49            // java#3 = Fieldref           #15.#50        // io/test/JavapTest.info:Ljava/lang/String;#4 = Fieldref           #15.#51        // io/test/JavapTest.flag:Z#5 = Fieldref           #15.#52        // io/test/JavapTest.num:I#6 = Fieldref           #15.#53        // io/test/JavapTest.gender:C#7 = Fieldref           #54.#55        // java/lang/System.out:Ljava/io/PrintStream;#8 = Class              #56            // java/lang/StringBuilder#9 = Methodref          #8.#48         // java/lang/StringBuilder."":()V#10 = Methodref          #8.#57         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;#11 = Methodref          #8.#58         // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;#12 = Methodref          #8.#59         // java/lang/StringBuilder.toString:()Ljava/lang/String;#13 = Methodref          #60.#61        // java/io/PrintStream.println:(Ljava/lang/String;)V#14 = String             #62            // www.baidu.com#15 = Class              #63            // io/test/JavapTest#16 = Class              #64            // java/lang/Object#17 = Utf8               num#18 = Utf8               I#19 = Utf8               flag#20 = Utf8               Z#21 = Utf8               gender#22 = Utf8               C#23 = Utf8               info#24 = Utf8               Ljava/lang/String;#25 = Utf8               COUNTS#26 = Utf8               ConstantValue#27 = Integer            1#28 = Utf8               #29 = Utf8               ()V#30 = Utf8               Code#31 = Utf8               LineNumberTable#32 = Utf8               LocalVariableTable#33 = Utf8               this#34 = Utf8               Lio/test/JavapTest;#35 = Utf8               (Z)V#36 = Utf8               falg#37 = Utf8               MethodParameters#38 = Utf8               methodPrivate#39 = Utf8               getNum#40 = Utf8               (I)I#41 = Utf8               i#42 = Utf8               showGender#43 = Utf8               ()C#44 = Utf8               showInfo#45 = Utf8               #46 = Utf8               SourceFile#47 = Utf8               JavapTest.java#48 = NameAndType        #28:#29        // "":()V#49 = Utf8               java#50 = NameAndType        #23:#24        // info:Ljava/lang/String;#51 = NameAndType        #19:#20        // flag:Z#52 = NameAndType        #17:#18        // num:I#53 = NameAndType        #21:#22        // gender:C#54 = Class              #65            // java/lang/System#55 = NameAndType        #66:#67        // out:Ljava/io/PrintStream;#56 = Utf8               java/lang/StringBuilder#57 = NameAndType        #68:#69        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;#58 = NameAndType        #68:#70        // append:(I)Ljava/lang/StringBuilder;#59 = NameAndType        #71:#72        // toString:()Ljava/lang/String;#60 = Class              #73            // java/io/PrintStream#61 = NameAndType        #74:#75        // println:(Ljava/lang/String;)V#62 = Utf8               www.baidu.com#63 = Utf8               io/test/JavapTest#64 = Utf8               java/lang/Object#65 = Utf8               java/lang/System#66 = Utf8               out#67 = Utf8               Ljava/io/PrintStream;#68 = Utf8               append#69 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;#70 = Utf8               (I)Ljava/lang/StringBuilder;#71 = Utf8               toString#72 = Utf8               ()Ljava/lang/String;#73 = Utf8               java/io/PrintStream#74 = Utf8               println#75 = Utf8               (Ljava/lang/String;)V
******************************字段表集合的信息**************************************
{private int num;   // 字段名descriptor: I   // 字段表集合的信息flags: ACC_PRIVATE   // 字段的访问标识boolean flag;descriptor: Zflags:protected char gender;descriptor: Cflags: ACC_PROTECTEDpublic java.lang.String info;descriptor: Ljava/lang/String;flags: ACC_PUBLICpublic static final int COUNTS;descriptor: Iflags: ACC_PUBLIC, ACC_STATIC, ACC_FINALConstantValue: int 1   // 常量字段的属性:ConstantValue
******************************方法表集合的信息**************************************public io.test.JavapTest();   // 无参构造器方法信息descriptor: ()Vflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."":()V4: aload_05: ldc           #2                  // String java7: putfield      #3                  // Field info:Ljava/lang/String;10: returnLineNumberTable:line 16: 0line 14: 4line 18: 10LocalVariableTable:Start  Length  Slot  Name   Signature0      11     0  this   Lio/test/JavapTest;private io.test.JavapTest(boolean);   // 单个参数构造器方法信息descriptor: (Z)Vflags: ACC_PRIVATECode:stack=2, locals=2, args_size=20: aload_01: invokespecial #1                  // Method java/lang/Object."":()V4: aload_05: ldc           #2                  // String java7: putfield      #3                  // Field info:Ljava/lang/String;10: aload_011: aload_012: getfield      #4                  // Field flag:Z15: putfield      #4                  // Field flag:Z18: returnLineNumberTable:line 19: 0line 14: 4line 20: 10line 21: 18LocalVariableTable:Start  Length  Slot  Name   Signature0      19     0  this   Lio/test/JavapTest;0      19     1  falg   ZMethodParameters:Name                           Flagsfalgprivate void methodPrivate();descriptor: ()Vflags: ACC_PRIVATECode:stack=0, locals=1, args_size=10: returnLineNumberTable:line 24: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       1     0  this   Lio/test/JavapTest;int getNum(int);descriptor: (I)Iflags:Code:stack=2, locals=2, args_size=20: aload_01: getfield      #5                  // Field num:I4: iload_15: iadd6: ireturnLineNumberTable:line 26: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       7     0  this   Lio/test/JavapTest;0       7     1     i   IMethodParameters:Name                           Flagsiprotected char showGender();descriptor: ()Cflags: ACC_PROTECTEDCode:stack=1, locals=1, args_size=10: aload_01: getfield      #6                  // Field gender:C4: ireturnLineNumberTable:line 29: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       5     0  this   Lio/test/JavapTest;public void showInfo();descriptor: ()V   // 方法的描述符:方法的形参列表、返回值类型flags: ACC_PUBLIC   // 方法的访问标识Code:   // 方法的Code属性stack=3, locals=2, args_size=1   // stack:操作数栈的最大深度   locals:局部变量表的长度   args_size:方法接受参数的个数
// 偏移量  操作码   操作数0: bipush        1002: istore_13: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;6: new           #8                  // class java/lang/StringBuilder9: dup10: invokespecial #9                  // Method java/lang/StringBuilder."":()V13: aload_014: getfield      #3                  // Field info:Ljava/lang/String;17: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;20: iload_121: invokevirtual #11                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;24: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;27: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V30: return
// 行号表:指明字节码指令的偏移量与java源代码中代码的行号的一一对应关系LineNumberTable:line 32: 0line 33: 3line 34: 30// 局部变量表:描述内部局部变量的相关信息LocalVariableTable:Start  Length  Slot  Name   Signature0      31     0  this   Lio/test/JavapTest;3      28     1     i   Istatic {};descriptor: ()Vflags: ACC_STATICCode:stack=1, locals=1, args_size=00: ldc           #14                 // String www.baidu.com2: astore_03: returnLineNumberTable:line 11: 0line 12: 3LocalVariableTable:Start  Length  Slot  Name   Signature
}
SourceFile: "JavapTest.java"   // 附加属性:指明当前字节码文件对应的源程序文件名

jclasslib展示的内容

总结

  1. 通过javap命令可以查看一个java类反汇编得到的Class文件版本号、常量池、访问标识、变量表、指令代码行号表等等信息。不显示类索引、父类索引、接口索引集合、()、 ()等结构

  2. 通过对前面例子代码反汇编文件的简单分析,可以发现,一个方法的执行通常会涉及下面几块内存的操作:

    1. java栈中:局部变量表、操作数栈。
    2. java堆。通过对象的地址引用去操作。
    3. 常量池。
    4. 其他如帧数据区、方法区的剩余部分等情况,测试中没有显示出来,这里说明一下。
  3. 平常,我们比较关注的是java类中每个方法的反汇编中的指令操作过程,这些指令都是顺序执行的,可以参考官方文档查看每个指令的含义,很简单:

总结

  1. 通过javap命令可以查看一个java类反汇编得到的Class文件版本号、常量池、访问标识、变量表、指令代码行号表等等信息。不显示类索引、父类索引、接口索引集合、()、 ()等结构

  2. 通过对前面例子代码反汇编文件的简单分析,可以发现,一个方法的执行通常会涉及下面几块内存的操作:

    1. java栈中:局部变量表、操作数栈。
    2. java堆。通过对象的地址引用去操作。
    3. 常量池。
    4. 其他如帧数据区、方法区的剩余部分等情况,测试中没有显示出来,这里说明一下。
  3. 平常,我们比较关注的是java类中每个方法的反汇编中的指令操作过程,这些指令都是顺序执行的,可以参考官方文档查看每个指令的含义,很简单:

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html

17.4 class文件结构 - 使用javap指令解析Class文件相关推荐

  1. 使用javap指令解析Class文件

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

  2. jvm中篇-04-Javap指令解析class文件

    jvm中篇-04-Javap指令解析class文件 解析字节码的作用 javac -g 操作 javap 的具体用法 使用举例 小结 234-237 解析字节码的作用 通过反编译生成的字节码文件,我们 ...

  3. Java的 Class字节码文件结构和内容全面解析【两万字】

    了解Class文件的结构组成,对于我们后续的JVM以及Java原理深入学习是很有帮助的,因为Class文件帮我们默默的做了很多事,比如.为什么对象方法中可以直接使用this变量?!本文将带领大家,一步 ...

  4. 使用批处理查看.class文件内容--javap指令

    想研究java的class的小伙伴注意了. 查看.class文件内容--javap指令 用到的指令是 javap -verbose 目标.class 文末给出了批处理脚本 首先我们看: 一个简易的输出 ...

  5. XCP实战系列介绍16-XCP标定过程指令解析

    本文框架 1.前言 2. XCP标定过程指令解析 1.前言 前面几篇文章我们介绍了XCP底层原理,配置方法及基于CANape,CANoe或Vehicle SPY进行观测或标定的方法,在本篇中我们将对标 ...

  6. 解读乐鑫 AT 指令解析器,解锁你不知道的用法

    文章首发于 『物联网学前班』公众号,欢迎关注.星标获取即时信息. 由于近期正好在做这个事情,所以今天就以乐鑫的 AT 指令为例,讲讲 AT 解析器设计有哪些事情,也算是个自己近期的学习总结了. 往期文 ...

  7. CPU指令解析及函数调用机制

    目录 一.CPU指令解析 最常用的mov指令 对栈进行push和pop 二.函数的调用机制 一.CPU指令解析 最常用的mov指令 指令中最常使用的是对寄存器和内存进行数据存储的 mov 指定数据的存 ...

  8. Windows BAT脚本常用指令解析

    BAT脚本入门 一.概述 首先解决第一个问题,什么是BAT脚本? BAT脚本也叫批处理文本,批处理文件是无格式的文本文件,它包含一条或多条命令.它的文件扩展名为 .bat 或 .cmd.在命令提示下键 ...

  9. 记: 对于SCPI指令以及相同类型指令解析器的指令压缩方式

    0x10 前言 SCPI是一个对人或者说用户十分友好的语言,采用了人性化的抽象与对于用户很友善的组成方式. 但是对于某些机器的设计就会很难受,而且当前的机器会在日后的不停更新导致当前的程序越来越呈现一 ...

最新文章

  1. SAP ECM的相关设定(ECN)
  2. ActiveMQ与xml rpc
  3. Django中扩展Paginator实现分页
  4. 电脑故障速排方法-显卡篇
  5. matlab 值法确定各指标权重,Matlab学习系列19. 熵值法确定权重
  6. INTEL和AMD两大巨头的前身
  7. protobuf windows lib链接库生成
  8. 2018四川高考文科21题
  9. Redhat/CentOS修改主机名
  10. seaborn箱线图_Seaborn线图的数据可视化
  11. 转载 - Linux使用技巧锦集
  12. Elasticsearch:Hadoop 大数据集成 (Hadoop => Elasticsearch)
  13. java定义一个盒子类box_C++定义一个Box(盒子)类 看完你就知道了
  14. java里面怎么生成备注时间_Android studio 创建java文件时 注解显示作者、日期、时间...
  15. 关于fi dd ler 手机抓包 网卡地址地址_超详细的网络抓包神器 tcpdump 使用指南
  16. win10 chrome被毒霸2345劫持主页处理过程与结果
  17. dropout keep_prob参数
  18. 百度大脑人体分析服务3月上新盘点
  19. ESP8266远程控制台灯(硬件软件详解)
  20. ArcGIS制图——单图层道路压盖处理

热门文章

  1. 从日志文件解决ArcGIS Server性能低下问题的步骤(1)
  2. 2021论文_汽车无钥匙进入系统中的抗干扰-重放攻击的防御机制
  3. led显示屏的合理亮度是多少?
  4. 在WTM中使用FreeSql
  5. RH124(12)----Linux中的软件管理
  6. 设计模式(5)之七大原则之开闭原则
  7. Sim control
  8. python判断合法IP并区分内网和外网地址
  9. CSS之左右固定,中间自适应
  10. hadoop集群部署