java -p_说说javap命令

javap定义

javap是 Java class文件分解器,可以反编译(即对javac编译的文件进行反编译),也可以查看java编译器生成的字节码。用于分解class文件。

测试类

public class JavapTest {

private static final int _P_1 = 1;

public static final int _P_2 = 2;

public static void main(String[] args) {

int m = 0, n = 0;

for (int i = 0; i < 10; i++) {

m = m++;

n = ++n;

}

System.out.println("m = " + m);

System.out.println("n = " + n);

}

}

javap命令参数

C:>javap -help

用法: javap

其中, 可能的选项包括:

-help --help -? 输出此用法消息

-version 版本信息

-v -verbose 输出附加信息

-l 输出行号和本地变量表

-public 仅显示公共类和成员

-protected 显示受保护的/公共类和成员

-package 显示程序包/受保护的/公共类

和成员 (默认)

-p -private 显示所有类和成员

-c 对代码进行反汇编

-s 输出内部类型签名

-sysinfo 显示正在处理的类的

系统信息 (路径, 大小, 日期, MD5 散列)

-constants 显示静态最终常量

-classpath 指定查找用户类文件的位置

-bootclasspath 覆盖引导类文件的位置

javap -version

C:>javap -version

1.7.0_71

显示java版本

javap -p

C:\Users\user\Desktop>javap -p JavapTest.class

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

private static final int _P_1;

public static final int _P_2;

public com.method.handler.JavapTest();

public static void main(java.lang.String[]);

private void say();

}

显示类所有可访问修饰符范围》private的成员

javap -public

C:\Users\user\Desktop>javap -public JavapTest.class

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

public static final int _P_2;

public com.method.handler.JavapTest();

public static void main(java.lang.String[]);

}

显示类的public成员

javap -protected

C:\Users\user\Desktop>javap -protected JavapTest.class

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

public static final int _P_2;

public com.method.handler.JavapTest();

public static void main(java.lang.String[]);

}

显示类所有可访问修饰符范围》protected的成员

javap -l

C:\Users\user\Desktop>javap -p -l JavapTest.class

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

private static final int _P_1;

public static final int _P_2;

public com.method.handler.JavapTest();

LineNumberTable:

line 6: 0

public static void main(java.lang.String[]);

LineNumberTable:

line 12: 0

line 13: 4

line 14: 12

line 15: 17

line 13: 22

line 17: 28

line 18: 53

line 19: 78

private void say();

LineNumberTable:

line 23: 0

line 24: 8

}

输出行号和本地变量表?看的不是很明白

javap -package

C:\Users\user\Desktop>javap -package JavapTest.class

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

public static final int _P_2;

public com.method.handler.JavapTest();

public static void main(java.lang.String[]);

}

与javap -public作用类似

javap -v/-p -v

C:\Users\user\Desktop>javap -p -v JavapTest.class

Classfile /C:/Users/frinder_liu/Desktop/JavapTest.class

Last modified 2016-4-27; size 911 bytes

MD5 checksum e903be7495f5c462d6459a792e063628

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest

SourceFile: “JavapTest.java”

minor version: 0

major version: 51

flags: ACC_PUBLIC, ACC_SUPER

Constant pool:

#1 = Methodref #13.#30 // java/lang/Object.""?)V

#2 = Fieldref #31.#32 // java/lang/System.out:Ljava/io/PrintStream;

#3 = Class #33 // java/lang/StringBuilder

#4 = Methodref #3.#30 // java/lang/StringBuilder.""?)V

#5 = String #34 // m =

#6 = Methodref #3.#35 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilde

r;

#7 = Methodref #3.#36 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

#8 = Methodref #3.#37 // java/lang/StringBuilder.toString:()Ljava/lang/String;

#9 = Methodref #38.#39 // java/io/PrintStream.println:(Ljava/lang/String;)V

#10 = String #40 // n =

#11 = String #41 // hello world…

#12 = Class #42 // com/method/handler/JavapTest

#13 = Class #43 // java/lang/Object

#14 = Utf8 _P_1

#15 = Utf8 I

#16 = Utf8 ConstantValue

#17 = Integer 1

#18 = Utf8 _P_2

#19 = Integer 2

#20 = Utf8

#21 = Utf8 ()V

#22 = Utf8 Code

#23 = Utf8 LineNumberTable

#24 = Utf8 main

#25 = Utf8 ([Ljava/lang/String;)V

#26 = Utf8 StackMapTable

#27 = Utf8 say

#28 = Utf8 SourceFile

#29 = Utf8 JavapTest.java

#30 = NameAndType #20:#21 // “”?)V

#31 = Class #44 // java/lang/System

#32 = NameAndType #45:#46 // out:Ljava/io/PrintStream;

#33 = Utf8 java/lang/StringBuilder

#34 = Utf8 m =

#35 = NameAndType #47:#48 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

#36 = NameAndType #47:#49 // append:(I)Ljava/lang/StringBuilder;

#37 = NameAndType #50:#51 // toString:()Ljava/lang/String;

#38 = Class #52 // java/io/PrintStream

#39 = NameAndType #53:#54 // println:(Ljava/lang/String;)V

#40 = Utf8 n =

#41 = Utf8 hello world…

#42 = Utf8 com/method/handler/JavapTest

#43 = Utf8 java/lang/Object

#44 = Utf8 java/lang/System

#45 = Utf8 out

#46 = Utf8 Ljava/io/PrintStream;

#47 = Utf8 append

#48 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;

#49 = Utf8 (I)Ljava/lang/StringBuilder;

#50 = Utf8 toString

#51 = Utf8 ()Ljava/lang/String;

#52 = Utf8 java/io/PrintStream

#53 = Utf8 println

#54 = Utf8 (Ljava/lang/String;)V

{

private static final int _P_1;

flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL

ConstantValue: int 1

public static final int _P_2;

flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

ConstantValue: int 2

public com.method.handler.JavapTest();

flags: ACC_PUBLIC

Code:

stack=1, locals=1, args_size=1

0: aload_0

1: invokespecial #1 // Method java/lang/Object.""?)V

4: return

LineNumberTable:

line 6: 0

public static void main(java.lang.String[]);

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=3, locals=4, args_size=1

0: iconst_0

1: istore_1

2: iconst_0

3: istore_2

4: iconst_0

5: istore_3

6: iload_3

7: bipush 10

9: if_icmpge 28

12: iload_1

13: iinc 1, 1

16: istore_1

17: iinc 2, 1

20: iload_2

21: istore_2

22: iinc 3, 1

25: goto 6

28: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

31: new #3 // class java/lang/StringBuilder

34: dup

35: invokespecial #4 // Method java/lang/StringBuilder.""?)V

38: ldc #5 // String m =

40: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/St

ringBuilder;

43: iload_1

44: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

47: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;

50: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

53: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

56: new #3 // class java/lang/StringBuilder

59: dup

60: invokespecial #4 // Method java/lang/StringBuilder.""?)V

63: ldc #10 // String n =

65: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/St

ringBuilder;

68: iload_2

69: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

72: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;

75: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

78: return

LineNumberTable:

line 12: 0

line 13: 4

line 14: 12

line 15: 17

line 13: 22

line 17: 28

line 18: 53

line 19: 78

StackMapTable: number_of_entries = 2

frame_type = 254 /* append /

offset_delta = 6

locals = [ int, int, int ]

frame_type = 250 / chop */

offset_delta = 21

private void say();

flags: ACC_PRIVATE

Code:

stack=2, locals=1, args_size=1

0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

3: ldc #11 // String hello world…

5: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

8: return

LineNumberTable:

line 23: 0

line 24: 8

}

命令说明是:输出附加信息

class文件的路径、最后修改时间、文件大小等

类的全路径、源(java)文件等

常量池

常量定义、值

构造方法

程序调用及执行逻辑(这个涉及的内容就比较多了)

总之,javap -v命令是很强大的一个命令!

javap -c

C:\Users\user\Desktop>javap -c JavapTest.class

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

public static final int _P_2;

public com.method.handler.JavapTest();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object.""?)V

4: return

public static void main(java.lang.String[]);

Code:

0: iconst_0

1: istore_1

2: iconst_0

3: istore_2

4: iconst_0

5: istore_3

6: iload_3

7: bipush 10

9: if_icmpge 28

12: iload_1

13: iinc 1, 1

16: istore_1

17: iinc 2, 1

20: iload_2

21: istore_2

22: iinc 3, 1

25: goto 6

28: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

31: new #3 // class java/lang/StringBuilder

34: dup

35: invokespecial #4 // Method java/lang/StringBuilder.""?)V

38: ldc #5 // String m =

40: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Stri

ngBuilder;

43: iload_1

44: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

47: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;

50: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

53: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;

56: new #3 // class java/lang/StringBuilder

59: dup

60: invokespecial #4 // Method java/lang/StringBuilder.""?)V

63: ldc #10 // String n =

65: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Stri

ngBuilder;

68: iload_2

69: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

72: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;

75: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

78: return

}

其实,javap -c 输出内部javap -v中已经有了,我们详细介绍下javap -c命令的输出内容

0: iconst_0 前面0:表示执行的顺序,iconst_0把值 0 放入栈顶,_0中的0代表压栈的值,如:iconst_5,即把5压入栈顶

1: istore_1 将栈顶的值放入变量1 中,_1代表变量的序列,本例中为:m,如:istore_2即为变量n赋值

6: iload_3 将变量3 即 i 的的值放入栈顶,与iconst不同的是,iload操作的值是已经定义好存在的值,iconst是定义时的压栈操作

13: iinc 1, 1 将变量1 的值加1

文章开头的demo中最终的结果是什么呢?

m = 0

n = 10

为什么呢?

我们来关注下这几行:

12: iload_1 – 将变量1 值放入栈项

13: iinc 1, 1 – 将变量1 增加1 变为2,栈顶值仍然是1。其中第一个1 表示变量,第二个1 表示增量

16: istore_1 – 将栈顶值赋值给变量1,变量1 仍然为1

17: iinc 2, 1 – 将变量2 增加1 变为2,栈顶值仍然是1。其中第一个2 表示变量,第二个1 表示增量

20: iload_2 – 将变量2 值放入栈顶

21: istore_2 – 将栈顶值赋值给变量2,变量2 值为2

记住一个点:

int m = 0, n = 0;

m = m++; – 会先将m值(即0)赋值给m后再++

n = ++n; – n先++后再把值赋值给n

此时,m = 0, n = 1;

这个地方有点绕,需要多看几次,理顺逻辑与关系!

这里可以参考下http://blog.csdn.net/junsure2012/article/details/7099222,讲的很详细也易懂!

javap -s/-p -s

C:\Users\user\Desktop>javap -p -s JavapTest.class

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

private static final int _P_1;

Signature: I

public static final int _P_2;

Signature: I

public com.method.handler.JavapTest();

Signature: ()V

public static void main(java.lang.String[]);

Signature: ([Ljava/lang/String;)V

private void say();

Signature: ()V

}

输出内部类型签名

javap -sysinfo/-p -sysinfo

C:\Users\user\Desktop>javap -sysinfo JavapTest.class

Classfile /C:/Users/user/Desktop/JavapTest.class

Last modified 2016-4-27; size 911 bytes

MD5 checksum 3f6dfcf7121785760b234224c5d135fd

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

public static final int _P_2;

public com.method.handler.JavapTest();

public static void main(java.lang.String[]);

}

显示正在处理的类的

系统信息 (路径, 大小, 日期, MD5 散列)

javap -constants/-p -constants

C:\Users\user\Desktop>javap -constants JavapTest.class

Compiled from “JavapTest.java”

public class com.method.handler.JavapTest {

public static final int _P_2 = 2;

public com.method.handler.JavapTest();

public static void main(java.lang.String[]);

}

显示静态最终常量

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值