【CSDN常见问题解答】Javap 的使用

本文介绍如何使用Javap命令查看Java编译器生成的字节码,通过对比字节码与源代码,揭示编译器内部工作原理。通过具体示例展示如何分析简单的Java程序,并解释字节码指令。

现在Java反编译工具或者插件非常多,也非常好用。比如我用的比较多得jd-gui。所以我们可能很少有机会使用到Javap命令。

这里我简单介绍下Javap,带各位入个门。介绍下这个命令不是使用它进行反编译,而是查看java编译器为我们生成 的字节码,通过比较字节码和源代码,我们可以发现很多的问题,一个很重要的作用就是了解很多编译器内部的工作机制。

下面我们通过具体的一个例子来简单的讲讲这个工具的作用,你不需要很深入的使用,这个简单的介绍和简单的使用就可以使你受益非浅。

首先我们先写一个非常简单的Java源文件:

class StringTest {
    public static void main(String[] args) {
        int i = 2;
        int j = 3;
    }
}
使用Javac 命令进行编译:

javac -g StringTest.java
最终有两个文件:

user ~/csdn_test/session1$ls -l
total 16
-rw-r--r--  1 user  staff  417  4  7 21:54 StringTest.class
-rw-r--r--  1 user  staff   99  4  7 21:53 StringTest.java

以上步骤涉及到JAVA环境变量配置,不会的自己google,或者发帖询问。这里使用了-g命令,意思是生成所有调试信息。(javac -help可以查看)

下面我们分2步来看看javap的显示结果:

1.不带任何参数使用javap StringTest


这里我们可以看到的信息有,从哪个文件(StringTest.java)编译过来的。类里面调用两个方法,一个是默认的构造函数,一个是main方法。在没有显式声明构造方法时,会产生一个默认构造方法。这也验证了,为什么一个对象,默认总是先执行构造函数,特别是在继承的场合下,使用这个命令就可以看的很清楚了。

2.使用-c参数javap -c StringTest


带-p参数将额外的打印字节码信息。前面的和不带参数的输出一样,后面的显示了方法的具体的字节码,从这个输出里面我们又可以了解更多的内容。

首先是编译器生成的的缺省构造方法的内容为调用父类的构造方法super(), main()方法的字节码信息的内容这里简单解释下:

Code:
   0:   iconst_2    //把2放到栈顶
   1:   istore_1    //把栈顶的值放到局部变量1中,即i中
   2:   iconst_3    //把3放到栈顶
   3:   istore_2    //把栈顶的值放到局部变量1中,即j中
   4:   return
所以再根据开始的java源码对照,对于 int i = 2;首先它会在栈中创建一个变量为i的引用,然后查找有没有字面值为2的地址,没找到,就开辟一个存放2这个字面值的地址,然后将i指向2的地址。j也是类似的。

 延伸学习:

1、如果将main中的变量换成String 类型的,然后看看javap的结果。

比如:

String a = "a";

String b = "b";

String ab = "ab";

String ab1 = a + b;

String ab2 = "a" + "b"


2、使用更多的参数分析其结果,如javap -l xxx javap -p xxx(提示 -p会显示private相关的)



这几个参数几乎就可以构成javap的最常使用的集合,最常用的应该还是-c选项,因为可以打印字节码的信息,关于这些字节码的详细涵义在Java 虚拟机规范中定义,感兴趣的可以自己去找找相关资料。

### Javap 工具概述 `javap` 是 Java 提供的一个反汇编工具,用于显示 `.class` 文件的内容。它可以解析由 `javac` 编译器生成的字节码文件,并将其转换为人类可读的形式[^1]。通过该工具,开发者可以查看类的结构、方法签名以及字段定义等内容。 以下是关于 `javap` 的一些基本信息: - **功能描述**: `javap` 主要用来分析已编译好的 Java 类文件。它能够展示类的成员变量、构造函数、普通方法以及其他元数据信息。对于学习 JVM 字节码或者排查某些运行时问题非常有用[^2]。 - **常见选项**: 下面列举了一些常用的命令行参数及其作用: - `-c`: 显示每个方法内的 Java 虚拟机指令 (即字节码)[^3]。 - `-v`, `-verbose`: 输出详细的附加信息,比如行号表、局部变量表等。 - `-s`: 打印出每条指令的操作数栈大小。 - `-l`: 展示源代码中的行号与本地变量映射关系。 - `-p`, `-private`: 包括私有成员在内的所有细节都会被打印出来,默认情况下只显示公共部分。 - `-sysinfo`: 获取额外的系统级详情,像访问标志位之类的属性也会一并呈现。 #### 使用案例演示 假设我们有一个简单的 Java 程序如下所示: ```java public class HelloWorld { public static void main(String[] args){ System.out.println("Hello World!"); } } ``` 先利用 `javac` 将其编译成二进制形式(`HelloWorld.class`)之后再调用 `javap` 查看内部实现逻辑: ```bash $ javap -c HelloWorld Compiled from "HelloWorld.java" public class HelloWorld { public HelloWorld(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #13 // String Hello World! 5: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return } ``` 以上输出解释了程序是如何一步步操作内存从而完成字符串输出工作的过程。 ### 总结说明 综上所述,`javap` 不仅是一个强大的教学辅助手段,在实际开发过程中同样扮演着不可或缺的角色。无论是理解复杂框架的工作原理还是定位难以捉摸的性能瓶颈,熟练掌握此工具有助于提升工作效率和技术水平。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值