Java基础从0开始---工具javap讲解

Java-工具javap讲解

  javap,是Java class文件分解器,反编译class文件,也可以查看java编译器生成的字节码。主要用于分解class文件。学习这个工具之前可以先去简单了解一下class类文件结构。

基本语法

命令格式:

1
javap [option] class文件(没有后缀名)

如果[option]为空,javap将输出传递给它的类的public域及方法,并输出到标准输出设备上(默认I/O为控制台)。如下代码,先javac编译源码,然后javap反编译class文件,注意不需要添加“.class”后缀。源码如下:

package com.xxo.demo.util;

/**
 * Created by xiaoxiaomo on 2016/3/31.
 */
public class JavapDemo {
    private int num = 10 ;
    public static String name = "momo" ;

    public static void main(String[] args) {
        String a = name ;
        String b = "abc" ;
        String c = a+b ;
        System.out.println(c);
    }
}

  • 下面来看一下javap的一些选项(常用的)
javap -help #输出 javap 的帮助信息。
javap  -l   #输出行及局部变量表。
javap -public #只显示public类及成员。
javap -protected #只显示protected和public类及成员。
javap -package #只显示包、protected和public类及成员。这是缺省设置。
javap -private #显示所有类和成员。
javap -s 输出内部类型签名。
javap -c #输出类中各方法的未解析的代码,即构成Java字节码的指令。
javap -verbose #输出堆栈大小、各方法的locals及args数,以及class文件的编译版本

javap -l 命令

public com.xxo.demo.util.JavapDemo(); 表示的默认的无参构造函数,

javap -pub|pro|pac|pri

  • 来简单看一下javap -public

就会显示出类中所用的public的类,构造方法,全局变量,局部变量就不会在此显示:

    public class com.xxo.demo.util.JavapDemo extends java.lang.Object{//类信息
        public static java.lang.String name;//public全部变量
        public com.xxo.demo.util.JavapDemo();//默认的构造方法
        public static void main(java.lang.String[]);//main方法
    }

下面来修改一下源代码,

  1. 私有化一下默认构造方法,然后重写一下带参构造方法
  2. 定义一个protected的全局变量
  3. private的HashMap类型的变量
  4. 修改后javac编译源码

源码如下

    package com.xxo.demo.util;

    import java.util.HashMap;

    /**
     * javap Demo
     * Created by xiaoxiaomo on 2016/3/31.
     */
    public class JavapDemo {
        private int num = 10 ;//私有全局变量
        public static String name = "momo" ;//共有全局变量
        protected Double height = 175.0 ;//protected
        private HashMap map ;

        private JavapDemo() {}
        public JavapDemo(int num) {
            this.num = num;
        }

        public static void main(String[] args) {
            String a = name ;
            String b = "abc" ;
            String c = a+b ;
            System.out.println(c);
        }
    }
  • 使用javap -protected查看,显示protected和public类及成员:

  • 使用javap -package查看,会显示包、protected和public类及成员:

  • 使用javap -private查看,会显示所用成员:

javap -c 命令

javap -c #输出类中各方法的未解析的代码,即构成Java字节码的指令。我们这里还是使用上例中的源码,输入命令:

1
$  javap -c JavapDemo
  • 编译后结果:
    Compiled from "JavapDemo.java"                                                             
    public class com.xxo.demo.util.JavapDemo extends java.lang.Object{                         
    public static java.lang.String name; //静态的全局变量name

    protected java.lang.Double height;//Double类型的变量height

    public com.xxo.demo.util.JavapDemo(int);//带参构造函数
      Code:                                                                                    
       0:   aload0 //将引用类型的局部变量加载到操作栈,即this
       1:   invokespecial   #1; //Method java/lang/Object."":()V //实例化对象this  
       4:   aload0 //将引用类型的局部变量加载到操作栈,即this      
       5:   bipush  10 //将一个常量加载到操作数栈,10
       7:   putfield        #2; //Field num:I //设置类中字段this.num的值为10
       10:  aload0    //加载局部变量表中的数据到操作栈中,即this  
       11:  ldc2w  #3; //double 175.0d  //将double类型的常量175.0d加载到操作数栈
       14:  invokestatic    #5; //Method java/lang/Double.valueOf:(D)Ljava/lang/Double;//调Double的valueOf方法
       17:  putfield        #6; //Field height:Ljava/lang/Double;//设置类中字段this.height的值
       20:  aload0 //加载局部变量表中的数据到操作栈中,即this
       21:  iload1 // 将int类型的局部变量加载到操作栈,即方法传递的num
       22:  putfield        #2; //Field num:I //设置类中字段this.num的值为num
       25:  return  //没有返回值

    public static void main(java.lang.String[]); //main方法         
      Code:                                                                                    
       0:   getstatic       #7; //Field name:Ljava/lang/String; //获取静态变量name,并压入栈顶
       3:   astore1    //将变量从操作数栈存储到局部变量中,(弹栈),即存入a中
       4:   ldc     #8; //String abc //字符串常量加载到操作数栈,abc
       6:   astore2    //将abc存储到局部变量表中,b中
       7:   new     #9; //class java/lang/StringBuilder  //创建一个StringBuilder对象                                      
       10:  dup        //直接操作操作数栈
       11:  invokespecial   #10; //Method java/lang/StringBuilder."":()V //
       14:  aload1 //加载局部变量表中的数据到操作栈中,即a的数据(第四条指令把a已加载到局部变量表中)
       15:  invokevirtual   #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
                    //调用Builder的append方法
       18:  aload2 //加载局部变量表中的数据到操作栈中,即b的数据
       19:  invokevirtual   #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
                    //调用Builder的append方法                                                                   
       22:  invokevirtual   #12; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;//调用Builder的toString方法

       25:  astore3 //将a+b的结果存储到局部变量表中,即c中
       26:  getstatic       #13; //Field java/lang/System.out:Ljava/io/PrintStream;//获取输出流
       29:  aload3 //加载局部变量表中的数据到操作栈中(第25条指令把c加载到了局部变量表)
       30:  invokevirtual   #14; //Method java/io/PrintStream.println:(Ljava/lang/String;)V //并输出打印
       33:  return //没有返回值

    static {};                                                                                 
      Code:                                                                                    
       0:   ldc     #15; //String momo   //字符串常量加载到操作数栈,"momo"
       2:   putstatic       #7; //Field name:Ljava/lang/String; //设置类中字段name的值为momo
       5:   return //没有返回值

    }

javap -verbose

    Compiled from "JavapDemo.java"
    public class com.xxo.demo.util.JavapDemo extends java.lang.Object
      SourceFile: "JavapDemo.java"
      minor version: 0
      major version: 50
      Constant pool:
    const #1 = Method       #17.#36;        //  java/lang/Object."":()V
    const #2 = Field        #16.#37;        //  com/xxo/demo/util/JavapDemo.num:I
    const #3 = double       175.0d;
    const #5 = Method       #38.#39;        //  java/lang/Double.valueOf:(D)Ljava/lang/Double; const #6 = Field        #16.#40;        //  com/xxo/demo/util/JavapDemo.height:Ljava/lang/Double;
    const #7 = Field        #16.#41;        //  com/xxo/demo/util/JavapDemo.name:Ljava/lang/String;
    const #8 = String       #42;    //  abc
    const #9 = class        #43;    //  java/lang/StringBuilder
    const #10 = Method      #9.#36; //  java/lang/StringBuilder."":()V
    const #11 = Method      #9.#44; //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    const #12 = Method      #9.#45; //  java/lang/StringBuilder.toString:()Ljava/lang/String;
    const #13 = Field       #46.#47;        //  java/lang/System.out:Ljava/io/PrintStream;
    const #14 = Method      #48.#49;        //  java/io/PrintStream.println:(Ljava/lang/String;)V
    const #15 = String      #50;    //  momo
    const #16 = class       #51;    //  com/xxo/demo/util/JavapDemo
    const #17 = class       #52;    //  java/lang/Object
    const #18 = Asciz       num;
    const #19 = Asciz       I;
    const #20 = Asciz       name;
    const #21 = Asciz       Ljava/lang/String;;
    const #22 = Asciz       height;
    const #23 = Asciz       Ljava/lang/Double;;
    const #24 = Asciz       map;
    const #25 = Asciz       Ljava/util/HashMap;;
    const #26 = Asciz       ;
    const #27 = Asciz       ()V;
    const #28 = Asciz       Code;
    const #29 = Asciz       LineNumberTable;
    const #30 = Asciz       (I)V;
    const #31 = Asciz       main;
    const #32 = Asciz       ([Ljava/lang/String;)V;
    const #33 = Asciz       ;
    const #34 = Asciz       SourceFile;
    const #35 = Asciz       JavapDemo.java;
    const #36 = NameAndType #26:#27;//  "":()V
    const #37 = NameAndType #18:#19;//  num:I
    const #38 = class       #53;    //  java/lang/Double
    const #39 = NameAndType #54:#55;//  valueOf:(D)Ljava/lang/Double;
    const #40 = NameAndType #22:#23;//  height:Ljava/lang/Double;
    const #41 = NameAndType #20:#21;//  name:Ljava/lang/String;
    const #42 = Asciz       abc;
    const #43 = Asciz       java/lang/StringBuilder;
    const #44 = NameAndType #56:#57;//  append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    const #45 = NameAndType #58:#59;//  toString:()Ljava/lang/String;
    const #46 = class       #60;    //  java/lang/System
    const #47 = NameAndType #61:#62;//  out:Ljava/io/PrintStream;
    const #48 = class       #63;    //  java/io/PrintStream
    const #49 = NameAndType #64:#65;//  println:(Ljava/lang/String;)V
    const #50 = Asciz       momo;
    const #51 = Asciz       com/xxo/demo/util/JavapDemo;
    const #52 = Asciz       java/lang/Object;
    const #53 = Asciz       java/lang/Double;
    const #54 = Asciz       valueOf;
    const #55 = Asciz       (D)Ljava/lang/Double;;
    const #56 = Asciz       append;
    const #57 = Asciz       (Ljava/lang/String;)Ljava/lang/StringBuilder;;
    const #58 = Asciz       toString;
    const #59 = Asciz       ()Ljava/lang/String;;
    const #60 = Asciz       java/lang/System;
    const #61 = Asciz       out;
    const #62 = Asciz       Ljava/io/PrintStream;;
    const #63 = Asciz       java/io/PrintStream;
    const #64 = Asciz       println;
    const #65 = Asciz       (Ljava/lang/String;)V;

    {
    public static java.lang.String name;

    protected java.lang.Double height;

    public com/xxo.demo.util.JavapDemo(int);
      Code:
       Stack=3, Locals=2, Argssize=2
       0:   aload0
       1:   invokespecial   #1; //Method java/lang/Object."":()V
       4:   aload0
       5:   bipush  10
       7:   putfield        #2; //Field num:I
       10:  aload0
       11:  ldc2w  #3; //double 175.0d
       14:  invokestatic    #5; //Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
       17:  putfield        #6; //Field height:Ljava/lang/Double;
       20:  aload0
       21:  iload1
       22:  putfield        #2; //Field num:I
       25:  return
      LineNumberTable:
       line 16: 0
       line 10: 4
       line 12: 10
       line 17: 20
       line 18: 25


    public static void main(java.lang.String[]);
      Code:
       Stack=2, Locals=4, Argssize=1
       0:   getstatic       #7; //Field name:Ljava/lang/String;
       3:   astore_1
       4:   ldc     #8; //String abc
       6:   astore2
       7:   new     #9; //class java/lang/StringBuilder
       10:  dup
       11:  invokespecial   #10; //Method java/lang/StringBuilder."":()V
       14:  aload1
       15:  invokevirtual   #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       18:  aload2
       19:  invokevirtual   #11; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       22:  invokevirtual   #12; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

       25:  astore3
       26:  getstatic       #13; //Field java/lang/System.out:Ljava/io/PrintStream;
       29:  aload3
       30:  invokevirtual   #14; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       33:  return
      LineNumberTable:
       line 21: 0
       line 22: 4
       line 23: 7
       line 24: 26
       line 25: 33


    static {};
      Code:
       Stack=1, Locals=0, Argssize=0 //
       0:   ldc     #15; //String momo
       2:   putstatic       #7; //Field name:Ljava/lang/String;
       5:   return
      LineNumberTable:
       line 11: 0

    }

本篇博客就不一一讲解字节码指令的具体含义了,在后面的一篇博客”java-字节码“,会详细的讲解字节码指令的具体含义。




1.除非注明,博文均为原创,转载请标明地址: http://blog.xiaoxiaomo.com/2016/03/31/Java-工具javap讲解/
2.文章作者: 小小默
3.发布时间:2016年03月31日 - 14时17分

你可能感兴趣的:(Java)