反编译不完全的代码(自己动手写开发工具总结)

反编译工具并不能完全地把字节码反编译成Java代码,因此有的字节码反编译后的代码中会出现一些JVM指令。下面通过这几个例子讲解下。

1.      下面代码是从商业项目SwisSQL的SQLCache类反编译以后的一段代码:

public static String getConvertedSQL(String gvnSQL){

     try{

                    PUSH(String)SQLTable.get(gvnSQL);

           }catch(Exceptione){

                    returnnull;

                   }

                   returnPOP;

         }

         其中“PUSH(String)SQLTable.get(gvnSQL);”这句的意思是把SQLTable.get(gvnSQL)的返回值压栈,最后一句就是把刚才压入栈中的值弹出来并返回。其等效于:

         publicstatic String getConvertedSQL(String gvnSQL){

                   Stringstr=null;

                   try{

                            str=(String)SQLTable.get(gvnSQL);

                   }catch(Exceptione){

                            return null;

                   }

                   returnstr;

         }

2.      下面的代码是SWT-Designer的NameCheckTitleAreaDialog类反编译以后的一段:

public class NameCheckTitleAreaDialog extendsTitleAreaDialog{

           staticClass class$0;

           …..

           protected intcheckName(String name,String checkMethodName){

                    ……

                    PUSHclass$0;

                    DUP

                    If(POP==null){

                             POP

                             try

{

                                PUSH(Class.forName(“org.eclipse.jdt.internal.corext.refactoring.Checks”));

                            }catch(ClassNotFoundExceptionPUSH){

                               PUSH new NoClassDefFoundError;

                               DUP_X1

                               SWAP

                               ((UNCONSTRUCTED)POP).NoClassDefFoundError(((Throwable)POP).getMessage());

                               throw POP;

                             }

                             PUSH class$0=POP;

}//endif

……..

3.      这里简单介绍几个常见的JVM指令:

DUP——复制栈顶值;

DUP2——将栈前两个值复制;

DUP_X1——复制栈顶值,并且将其下移两个位置。

DUP2_X1——将栈前两个值复制,并且将其下移两个位置。

DUP_X2——复制栈顶值,并且将其下移3个位置。

DUP2_X2——将栈前两个值复制,并且将其下移3个位置。

SWAP——交换栈中前两个值的位置

4.      简单解释下这里用到的JVM指令:

程序首先调用“PUSH class$0”将class$0压入栈,然后调用DUP将栈顶的值复制一份加入栈,此时栈中有两个class$0变量。

“if(POP==null)”:首先”POP”出栈,判断此变量(即class$0)是否为空,如果否的话,则跳过此段代码,如果是的话,则首先执行”POP“将另一class$0变量弹出。调用”Class.forName(“org.eclipse.jdt.internal.corext.refactoring.Checks”)”反射取得Checks类对象,然后将类对象实例压栈,如果反射调用成功,则调用“PUSH class$0=POP;”将栈中的类对象弹出来赋值给class$0变量。

如果调用”Class.forName(“org.eclipse.jdt.internal.corext.refactoring.Checks”)”的时候发生异常,则”catch(ClassNotFoundExceptionPUSH)”这句会首先将捕捉到的异常变量压栈,”PUSH new NoClassDefFoundError;”是创建一个NoClassDefFoundError类变量(注意此处不是调用的NoClassDefFoundError的构造函数,所以并没有实例化,只是创建一个变量而已)然后压栈。

调用“DUP_X1”,将栈顶值(即NoClassDefFoundError的变量)复制一份并下移两个位置;调用“SWAP”交换栈前两个元素的位置。

“((UNCONSTRUCTED)POP).NoClassDefFoundError(((Throwable)POP).getMessage());”中,虽然代码的顺序是先”((UNCONSTRUCTED)POP)”后”.NoClassDefFoundError(((Throwable)POP).getMessage()”,但是真正的运行顺序是调用构造函数“.NoClassDefFoundError(((Throwable)POP).getMessage()”,在这里将“抛出的ClassNotFoundException异常的的实例”弹出来,调用其getMessage()得到String变量作为构造函数NoClassDefFoundError的变量“,由于栈中随后一个元素是刚才被初始化的副本,所以就可以把最后一个元素弹出Throw了。

5.      翻译后的代码如下:

public class NameCheckTitleAreaDialog extendsTitleAreaDialog{

           staticClass class$0;

           protectedint checkName(String name,String checkMethodName){

                    if(class$0==null){

                             try{

                                       class$0=(Class.forName(“org.eclipse.jdt.internal.corext.refactoring.Checks”));

                             }catch(ClassNotFoundExceptione){

                                       Thrownew NoClassDefFoundError(((Throwable)e).getMessage());

                             }

                    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值