反编译不完全的代码(自己动手写开发工具总结)
2015-04-20 19:32
337 查看
反编译工具并不能完全地把字节码反编译成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());
}
}
}
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());
}
}
}
相关文章推荐
- atitit.自己动手开发编译器and解释器(2) ------语法分析,语义分析,代码生成--attilax总结
- atitit.自己动手开发编译器and解释器(2) ------语法分析,语义分析,代码生成--attilax总结
- atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结
- atitit.自己动手开发编译器and解释器(1) ------词法分析--attilax总结
- 自己动手打造代码压缩合并工具
- 工欲善其事,必先利其器 软件工具开发关键词 protractor自动化测试工具 RegexBuddy正则 CodeSmith,LightSwitch:代码生成 CheatEngine:玩游戏修改内存值必备神器 ApkIDE:Android反编译工具 Reflector:反编译dll动态链接库
- iOS 开发工具 打造自己的代码
- 嵌入式开发第二日(man 手册、linux基本命令、vim编辑器、代码编译过程、编译工具、基本数据类型、控制流)
- iOS:使用Github托管自己本地的项目代码方式一:(Xcode方式:开发工具Xcode配置Git,由Xcode-->Source Control-->Commit)
- 开发环境以及工具,第一个自己的代码:Smile
- 自己动手开发智能聊天机器人完全指南(附python完整源码)
- 自己动手开发智能聊天机器人完全指南(附完整源码)
- webpack学习之三,开发,即使用source map,3个自动编译代码的工具
- 自己动手开发智能聊天机器人完全指南(附python完整源码)
- Atitit ide之道 开发工具之道 attilax著 v2 s22.docx Atitit ide开发工具之道 attilax总结 1. 代码编辑器功能 3 1.1. 关键词颜色 3 1.2.
- 1.4.3.自己动手安装交叉编译工具链1
- 开发工具——代码编辑器Sublime Text 3(配置总结)
- 开发性能测试工具——自己动手实现迭代功能
- Android开发linux下系统大模块编译、单模块编译、代码定位、指令总结
- 【干货】自己动手打造专属代码生成工具(完结篇)