From:http://hi.baidu.com/tianhuimin/blog/item/3fcb61d019e57b9fa1ec9c80.html
javap是jdk自带的一个工具,可以反编译,也可以查看java编译器生成的字节码,是分析代码的一个好工具。
javap - Java class文件分解器
分解class文件
摘要:
javap [ options ] class. . .
描述:
javap命令分解一个class文件,它根据options来决定到底输出什么。如果没有使用options,那么javap将会输出包,类里的 protected和public域以及类里的所有方法。javap将会把它们输出在标准输出上。来看这个例子,先编译下面这个类。
Java代码
1.import java.awt.*;
2. import java.applet.*;
3.
4. public class Uenucom extends Applet {
5. String date;
6. String email;
7.
8. public void init() {
9. resize(500,100);
10. date = getParameter("LAST_UPDATED");
11. email = getParameter("EMAIL");
12. }
13.
14. public void paint(Graphics g) {
15. g.drawString(date + " by ",100, 15);
16. g.drawString(email,290,15);
17. }
18. }
import java.awt.*;
import java.applet.*;
public class Uenucom extends Applet {
String date;
String email;
public void init() {
resize(500,100);
date = getParameter("LAST_UPDATED");
email = getParameter("EMAIL");
}
public void paint(Graphics g) {
g.drawString(date + " by ",100, 15);
g.drawString(email,290,15);
}
}
在命令行上键入javap Uenucom后,输出结果如下
Java代码
1.Compiled from Uenucom.java
2.public class Uenucom extends java.applet.Applet {
3. java.lang.String date;
4. java.lang.String email;
5. public Uenucom();
6. public void init();
7. public void paint(java.awt.Graphics);
8.}
Compiled from Uenucom.java
public class Uenucom extends java.applet.Applet {
java.lang.String date;
java.lang.String email;
public Uenucom();
public void init();
public void paint(java.awt.Graphics);
}
如果加入了-c,即javap -c Uenucom,那么输出结果如下
Java代码
1. Compiled from Uenucom.java
2.public class Uenucom extends java.applet.Applet {
3. java.lang.String date;
4. java.lang.String email;
5. public Uenucom();
6. public void init();
7. public void paint(java.awt.Graphics);
8.}
9.
10.Method Uenucom()
11. 0 aload_0
12. 1 invokespecial #1
13. 4 return
14.
15.Method void init()
16. 0 aload_0
17. 1 sipush 500
18. 4 bipush 100
19. 6 invokevirtual #2
20. 9 aload_0
21. 10 aload_0
22. 11 ldc #3
23. 13 invokevirtual #4
24. 16 putfield #5
25. 19 aload_0
26. 20 aload_0
27. 21 ldc #6
28. 23 invokevirtual #4
29. 26 putfield #7
30. 29 return
31.
32.Method void paint(java.awt.Graphics)
33. 0 aload_1
34. 1 new #8
35. 4 dup
36. 5 invokespecial #9
37. 8 aload_0
38. 9 getfield #5
39. 12 invokevirtual #10
40. 15 ldc #11
41. 17 invokevirtual #10
42. 20 invokevirtual #12
43. 23 bipush 100
44. 25 bipush 15
45. 27 invokevirtual #13
46. 30 aload_1
47. 31 aload_0
48. 32 getfield #7
49. 35 sipush 290
50. 38 bipush 15
51. 40 invokevirtual #13
52. 43 return
53.
Compiled from Uenucom.java
public class Uenucom extends java.applet.Applet {
java.lang.String date;
java.lang.String email;
public Uenucom();
public void init();
public void paint(java.awt.Graphics);
}
Method Uenucom()
0 aload_0
1 invokespecial #1
4 return
Method void init()
0 aload_0
1 sipush 500
4 bipush 100
6 invokevirtual #2
9 aload_0
10 aload_0
11 ldc #3
13 invokevirtual #4
16 putfield #5
19 aload_0
20 aload_0
21 ldc #6
23 invokevirtual #4
26 putfield #7
29 return
Method void paint(java.awt.Graphics)
0 aload_1
1 new #8
4 dup
5 invokespecial #9
8 aload_0
9 getfield #5
12 invokevirtual #10
15 ldc #11
17 invokevirtual #10
20 invokevirtual #12
23 bipush 100
25 bipush 15
27 invokevirtual #13
30 aload_1
31 aload_0
32 getfield #7
35 sipush 290
38 bipush 15
40 invokevirtual #13
43 return
当然,如果想分析这个文件,可以讲输出结果输出到一个文件里。可以这样写
javap -c Uenucom > F://test.txt
这样就会输出到F盘的test.txt文件中了。
选项:
-help 不说了
-l 输出行和变量的表
-public 只输出public方法和域
-protected 只输出public和protected类和成员
-package 只输出包,public和protected类和成员,这是默认的
-private 输出所有类和成员
-s 输出内部类型签名
-c 输出分解后的代码,例如,类中每一个方法内,包含java字节码的指令,
-verbose 输出栈大小,方法参数的个数
。。。
======================================================================
摘要: javap是一个很好的深入查看程序内部运行机制的工具,不过它有不同于汇编的自有格式的语句。本文
通过用javap对 i=i++ + ++i 这一特殊语言现象进行分析,带你进入javap的微观世界。============================================ ================================================
首先我们来了解一下javap命令及其基本用法。
javap是sun提供的对class文件进行反编译的工具,javap和javac、java等bin文件存放路径相同,当你配置好了环
境变量后,javap就和javac、java等命令的用法类似了。
javap最基本的用法,也是最常用的用法如下:
javap -[参数] test
其中,test是test.java文件经javac编译后产生的class文件名,也就是说,在javap之前,你必须用javac编译这
个文件,需要注意的一点是,在使用javap反编译.class文件时,不要带上其后缀名,否则会报错。
我们对javap最常用的参数是c,也就是形如 javap -c test 的用法,如果你还想对javap的参数进一步了解的话,
我向你推荐 www.javaresearch.org 的一篇文章《javap简介》,你可以在该网站的首页上通过查询该标题得到这
篇文章。下面我们进入正题:
•第一例
int i = 0;
i=i++ + ++i;
Code:
0: iconst_0 将 0 推到堆栈中//对应赋值语句 int i = 0;iconst_0中的0为初始值
1: istore_1 从堆栈中弹出这个值,并将它存储到局部变量表的索引 1 处 //对应赋值语句,上句是
赋值,这句是存储,索引1处即为i,因为没有其它变量,所以本例中局部变量的索引不变
2: iload_1 将局部变量表索引 1 处的值推到堆栈中//将局部变量索引1处的计算结果推入堆栈临时
存储,局部变量的索引从1开始,依此类推,这句意味着将变量i=0先推入堆栈临时存储
3: iinc 1, 1 局部变量表索引 1 处的变量加 1 //将变量i自加1,则此时变量i为1
6: iinc 1, 1 局部变量表索引 1 处的变量加 1 //再将变量i自加1,则此时变量i为2
9: iload_1 将局部变量表索引 1 处的值推到堆栈中//将变量i=2推入堆栈临时存储
10: iadd 从操作数堆栈中弹出两个整数并让它们相加。将得到的整数推回堆栈中//将两次暂存的
整数相加,即0+2=2
11: istore_1 从堆栈中弹出这个值,并将它存储到局部变量表的索引 1 处//把上步相加之结果弹出
堆栈
12: return 从堆栈中弹出值并将它推到调用方法的操作数栈中。退出方法//将i=2返回,计算结束
•第二例
int i=0;
i = ++i + i++;
Code:
0: iconst_0 将 0 推到堆栈中//对应赋值语句 int i = 0;iconst_0中的0为初始值
1: istore_1 从堆栈中弹出这个值,并将它存储到局部变量表的索引 1 处 //对应赋值语句,上句
是赋值,这句是存储
2: iinc 1, 1 局部变量表索引 1 处的变量加 1 //将变量i自加1,则此时变量i为1
5: iload_1 将局部变量表索引 1 处的值推到堆栈中//将变量i=1推入堆栈临时存储
6: iload_1 将局部变量表索引 1 处的值推到堆栈中//将变量i=1推入堆栈临时存储
7: iinc 1, 1 局部变量表索引 1 处的变量加 1 //再将变量i自加1,则此时变量i为2
10: iadd 从操作数堆栈中弹出两个整数并让它们相加。将得到的整数推回堆栈中//将两次暂存的
整数相加,即0+2=2 注意:虽然上步让i=2,但是并没有推入堆栈作存储
11: istore_1 从堆栈中弹出这个值,并将它存储到局部变量表的索引 1 处//把上步相加之结果弹出堆栈
12: return 从堆栈中弹出值并将它推到调用方法的操作数栈中。退出方法//将i=2返回,计算结束
======================================================================================
下面给出的是较为复杂一点的例子,供读者自行分析。
int i=0;
i= i++ + ++i;
int j=0;
j= ++j + ++j;
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: iinc 1, 1
9: iload_1
10: iadd
11: istore_1
12: iconst_0
13: istore_2
14: iinc 2, 1
17: iload_2
18: iinc 2, 1
21: iload_2
22: iadd
23: istore_2
24: return
参考资料
http://blog.csdn.net/myyate/archive/2007/07/24/1704852.aspx
http://www.javaeye.com/topic/466832
http://www.examda.com/JAVA/Instructs/050924/095749165.html
http://www.examda.com/linux/fudao/20070604/085826447.html