您的位置:首页 > 职场人生

用反编译理解程序

2006-01-19 15:56 211 查看
                                     用反编译理解程序

   以前看过很多汇编高手,在汇编领域学到一定的程度之后,在学习其他语言是,真的能学的更快,理解的更深,比如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到类试面试题目,这里我个人认为这只是一种分析程序的方法,不过当程序过于庞大复杂时,将不再试用。
   

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息