欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【JVM】Java 通过 javap 命令分析java汇编指令

程序员文章站 2022-07-12 20:29:54
...

 

 

javap是jdk自带的反解析工具。它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。
当然这些信息中,有些信息(如本地变量表、指令和代码行偏移量映射表、常量池中方法的参数名称等等)需要在使用javac编译成class文件时,指定参数才能输出,比如,你直接javac xx.java,就不会在生成对应的局部变量表等信息,如果你使用javac -g xx.java就可以生成所有相关信息了。如果你使用的eclipse,则默认情况下,eclipse在编译时会帮你生成局部变量表、指令和代码行偏移量映射表等信息的。
通过反编译生成的汇编代码,我们可以深入的了解java代码的工作机制。比如我们可以查看i++;这行代码实际运行时是先获取变量i的值,然后将这个值加1,最后再将加1后的值赋值给变量i。
通过局部变量表,我们可以查看局部变量的作用域范围、所在槽位等信息,甚至可以看到槽位复用等信息。

javap的用法格式:
javap <options> <classes>
其中classes就是你要反编译的class文件。
在命令行中直接输入javap或javap -help可以看到javap的options说明


 

javap -c .\HelloWord.class

 

 

package sample;
/**
 * @program:
 *
 * @description:
 *
 * @author: Mr.Guan
 *
 * @Mail: aaa@qq.com
 *
 * @create: 2020-05-27 13:35
 **/
public class HelloWord {


    /**
     * public class sample.HelloWord {
     *   public sample.HelloWord();
     *     Code:
     *        0: aload_0
     *        1: invokespecial #1                  // Method java/lang/Object."<init>":()V
     *        4: return
     *
     *   public int add();
     *     Code:
     *        0: iconst_1
     *        1: istore_1
     *        2: iconst_2
     *        3: istore_2
     *        4: iload_1
     *        5: iload_2
     *        6: iadd
     *        7: bipush        100
     *        9: imul
     *       10: istore_3
     *       11: iload_3
     *       12: ireturn
     *
     *   public static void main(java.lang.String[]);
     *     Code:
     *        0: new           #2                  // class sample/HelloWord
     *        3: dup
     *        4: invokespecial #3                  // Method "<init>":()V
     *        7: astore_1
     *        8: aload_1
     *        9: invokevirtual #4                  // Method add:()I
     *       12: istore_2
     *       13: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
     *       16: iload_2
     *       17: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
     *       20: return
     * }
     * @return
     */


    public int add(){
        /**
         *        0: iconst_1   //将值压入栈 int型常量值1进栈   //将值压入 main线程-栈FILO-add栈帧-操作数栈 中
         *        1: istore_1   //将栈顶int型数值存入第二个局部变量,从0开始计数
         */
        int a = 1;  //局部变量

        /**
         *        2: iconst_2
         *        3: istore_2
         */
        int b = 2;  //局部变量

        /**
         *        4: iload_1                //第二个int型局部变量进栈             a
         *        5: iload_2                //第三个int型局部变量进栈             b
         *        6: iadd                   //栈顶两int型数值相加,并且结果进栈    (a + b) = 3     计算完之后a b 都会出栈
         *        7: bipush        100      //将100压入栈顶   将8位带符号的整数压入栈   code顺序没有8   这个100代表第八个
         *
         *        9: imul                   //栈顶两int型数值相乘,并且结果进栈    3 * 100         计算完之后3  100 都会出栈
         *       10: istore_3               //300
         */
        int c = (a + b) * 100;  //局部变量

        /**
         *       11: iload_3        //第四个int型局部变量进栈,从0开始计数
         *       12: ireturn        //当前方法返回int             通过方法出口返回到 main栈帧
         */
        return c;   //方法出口
    }

    public static void main(String[] args) {

        HelloWord helloWord = new HelloWord();  //局部变量

        int add = helloWord.add();  //局部变量


        System.out.println(add);

    }

}

【JVM】Java 通过 javap 命令分析java汇编指令