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 -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文件的编译版本
public com.xxo.demo.util.JavapDemo(); 表示的默认的无参构造函数,
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方法
}
下面来修改一下源代码,
源码如下
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 #输出类中各方法的未解析的代码,即构成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 //没有返回值
}
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-字节码“,会详细的讲解字节码指令的具体含义。