用反编译理解程序
以前看过很多汇编高手,在汇编领域学到一定的程度之后,在学习其他语言是,真的能学的更快,理解的更深,比如c, java ,c++ 等等。。。。
我这里也有一个用java自带命令帮助我们理解程序的方法。
下面这段代码是关于(zt)变态java面试题中的第一个,问你下面这段代码#mmm处的运行结果?
我补充了一下,顺便用运行在虚拟机上的代码简单的说明下。
public class TestExamMethod {
public static void main(String[] args){
TestExamMethod instance = new TestExamMethod();
instance.test1();
}
public void test1(){
int x=4;
System.out.println("value is " +((x>4)?99.9:9)); //#mmm
System.out.println("value is " +((x>4)?99:9)); //#nnn
}
}
-------------------------------------------------------------------------------------------------------------
E:/wytest>javap -c TestExamMethod
Compiled from "TestExamMethod.java"
public class test.thinkinjava.TestExamMethod extends java.lang.Object{
public test.thinkinjava.TestExamMethod();
Code:
0: aload_0
1: invokespecial #9; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2; //class test/thinkinjava/TestExamMethod
3: dup
4: invokespecial #16; //Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #19; //Method test1:()V
12: return
public void test1();
Code:
0: iconst_4
1: istore_1
2: getstatic #28; //Field java/lang/System.out:Ljava/io/PrintStream;
5: new #30; //class java/lang/StringBuffer
8: dup
9: ldc #32; //String value is
11: invokespecial #35; //Method java/lang/StringBuffer."<init>":(Ljava/lan
g/String;)V
14: iload_1
15: iconst_4
16: if_icmple 25
19: ldc2_w #36; //double 99.9d
22: goto 28
25: ldc2_w #38; //double 9.0d
28: invokevirtual #43; //Method java/lang/StringBuffer.append:(D)Ljava/lan
g/StringBuffer;
31: invokevirtual #47; //Method java/lang/StringBuffer.toString:()Ljava/la
ng/String;
34: invokevirtual #52; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
37: getstatic #28; //Field java/lang/System.out:Ljava/io/PrintStream;
40: new #30; //class java/lang/StringBuffer
43: dup
44: ldc #32; //String value is
46: invokespecial #35; //Method java/lang/StringBuffer."<init>":(Ljava/lan
g/String;)V
49: iload_1
50: iconst_4
51: if_icmple 59
54: bipush 99
56: goto 61
59: bipush 9
61: invokevirtual #55; //Method java/lang/StringBuffer.append:(I)Ljava/lan
g/StringBuffer;
64: invokevirtual #47; //Method java/lang/StringBuffer.toString:()Ljava/la
ng/String;
67: invokevirtual #52; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
70: return
}
-----------------------------------------------------------------------------------
主要看test1()方法,先说明下概念:
1、bipush :将8位带符号的整数入栈,但要先将8位扩展为int需要的位数。
2、if_icmple :你可以简单的先理解为if()条件语句。。。
3、iconst_4 :将int类型常量4压入栈
4、iload_1 :从局部变量1中装载int
5、ldc2_w :把常量池中的long/double类型的项压入栈。
其他具体内容你可以查看 《深入Java虚拟机》查找。
借助反编译代码说明源代码运行结果:
System.out.println("value is " +((x>4)?99:9)); //#nnn
他在运行时,99 ---> int 类型,先压入栈 [ bipush 99 ]
然后 9 ----> int 类型 在压入栈 [bipush 9]
当然取出来运行的结果自然是: value is 9
System.out.println("value is " +((x>4)?99.9:9)); //#mmm
他在运行时,99.9 ---> double 类型,先压入栈 [ dc2_w #36; //double 99.9d ]
然后 9----> int类型, 但虚拟机这时将?前后的类型转型,规则和我们写 int + double 时一样。
所以这里 9 ---> 9.0 ---> double类型压入栈,[ ldc2_w #38; //double 9.0d ]
当然取出来运行的结果自然是: value is 9.0
同样,如果我们这是要运行 System.out.println("value is " +((x==4)?99:9.0));
结果应该是99.0 规则同样和 int + double 一样。
在java实现论坛上有10到类试面试题目,这里我个人认为这只是一种分析程序的方法,不过当程序过于庞大复杂时,将不再试用。