java反编译⼯具_Java开发必会的反编译知识(附⽀持对
Lambda进⾏反编译的⼯具)...
我之前推送过Java代码的编译与反编译,其中简单的介绍了Java编译与反编译相关的知识,最近给GitChat写《深⼊分析Java语法糖》的时候,⼜⽤到了很多反编译相关的知识,遂发现哪篇⽂章已有些过时。于是,这篇⽂章就这样呈现在你的⾯前了~
编程语⾔
在介绍编译和反编译之前,我们先来简单介绍下编程语⾔(Programming Language)。编程语⾔(Programming Language)分为低级语⾔(Low-level Language)和⾼级语⾔(High-level Language)。
机器语⾔(Machine Language)和汇编语⾔(Assembly Language)属于低级语⾔,直接⽤计算机指令编写程序。
⽽C、C++、Java、Python等属于⾼级语⾔,⽤语句(Statement)编写程序,语句是计算机指令的抽象表⽰。
举个例⼦,同样⼀个语句⽤C语⾔、汇编语⾔和机器语⾔分别表⽰如下:
计算机只能对数字做运算,符号、声⾳、图像在计算机内部都要⽤数字表⽰,指令也不例外,上表中的机器语⾔完全由⼗六进制数字组成。最早的程序员都是直接⽤机器语⾔编程,但是很⿇烦,需要查⼤量的表格来确定每个数字表⽰什么意思,编写出来的程序很不直观,⽽且容易出错,于是有了汇编语⾔,把机器语⾔中⼀组⼀组的数字⽤助记符(Mnemonic)表⽰,直接⽤这些助记符写出汇编程序,然后让汇编器(Assembler)去查表把助记符替换成数字,也就把汇编语⾔翻译成了机器语⾔。
但是,汇编语⾔⽤起来同样⽐较复杂,后⾯,就衍⽣出了Java、C、C++等⾼级语⾔。
什么是编译
上⾯提到语⾔有两种,⼀种低级语⾔,⼀种⾼级语⾔。可以这样简单的理解:低级语⾔是计算机认识的语⾔、⾼级语⾔是程序员认识的语⾔。
那么如何从⾼级语⾔转换成低级语⾔呢?这个过程其实就是编译。
从上⾯的例⼦还可以看出,C语⾔的语句和低级语⾔的指令之间不是简单的⼀⼀对应关系,⼀条a=b+1;语句要翻译成三条汇编或机器指令,这个过程称为编译(Compile),由编译器(Compiler)来完成,显然编译器的功能⽐汇编器要复杂得多。⽤C语⾔编写的程序必须经过编译转成机器指令才能被计算机执⾏,编译需要花⼀些时间,这是⽤⾼级语⾔编程的⼀个缺点,然⽽更多的是优点。⾸先,⽤C语⾔编程更容易,写出来的代码更紧凑,可读性更强,出了错也更容易改正。
将便于⼈编写、阅读、维护的⾼级计算机语⾔所写作的源代码程序,翻译为计算机能解读、运⾏的低阶机器语⾔的程序的过程就是编译。负责这⼀过程的处理的⼯具叫做编译器
现在我们知道了什么是编译,也知道了什么是编译器。不同的语⾔都有⾃⼰的编译器,Java语⾔中负责编译的编译器是⼀个命令:javac
javac是收录于JDK中的Java语⾔编译器。该⼯具可以将后缀名为.java的源⽂件编译为后缀名为.class的可以运⾏于Java虚拟机的字节码。
当我们写完⼀个HelloWorld.java⽂件后,我们可以使⽤javac HelloWorld.java命令来⽣成HelloWorld.class⽂件,这个class类型的⽂件是JVM可以识别的⽂件。通常我们认为这个过程叫做Java语⾔的编译。其实,class⽂件仍然不是机器能够识别的语⾔,因为机器只能识别机器语⾔,还需要JVM再将这种class⽂件类型字节码转换成机器可以识别的机器语⾔。
什么是反编译
反编译的过程与编译刚好相反,就是将已编译好的编程语⾔还原到未编译的状态,也就是出程序语⾔的源代码。就是将机器看得懂的语⾔
转换成程序员可以看得懂的语⾔。Java语⾔中的反编译⼀般指将class⽂件转换成java⽂件。
有了反编译⼯具,我们可以做很多事情,最主要的功能就是有了反编译⼯具,我们就能读得懂Java编译器⽣成的字节码。
Java反编译⼯具
本⽂主要介绍3个Java的反编译⼯具:javap、jad和CFR
javap
javap是jdk⾃带的⼀个⼯具,可以对代码反编译,也可以查看java编译器⽣成的字节码。javap和其他两个反编译⼯具最⼤的区别是他⽣成
的⽂件并不是java⽂件,也不像其他两个⼯具⽣成代码那样更容易理解。拿⼀段简单的代码举例,如我们想分析Java 7中的switch是如何⽀持String的,我们先有以下可以编译通过的源代码:
public class switchDemoString { public static void main(String[] args) { String str = "world"; switch (str) { case "hello": System.out.println("hello"); break; case 执⾏以下两个命令:
javac switchDemoString.javajavap -c switchDemoString.class
⽣成代码如下:
public class com.hollis.suguar.switchDemoString { public com.hollis.suguar.switchDemoString(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/O
我个⼈的理解,javap并没有将字节码反编译成java⽂件,⽽是⽣成了⼀种我们可以看得懂字节码。其实javap⽣成的⽂件仍然是字节码,只
是程序员可以稍微看得懂⼀些。如果你对字节码有所掌握,还是可以看得懂以上的代码的。其实就是把String转成hashcode,然后进⾏⽐较。
个⼈认为,⼀般情况下我们会⽤到javap命令的时候不多,⼀般只有在真的需要看字节码的时候才会⽤到。但是字节码中间暴露的东西是最
全的,你肯定有机会⽤到,⽐如我在分析synchronized的原理的时候就有是⽤到javap。通过javap⽣成的字节码,我发现synchronized底层依赖了ACC_SYNCHRONIZED标记和monitorenter、monitorexit两个指令来实现同步。
jad
jad是⼀个⽐较不错的反编译⼯具,只要下载⼀个执⾏⼯具,就可以实现对class⽂件的反编译了。还是上⾯的源代码,使⽤jad反编译后内
容如下:
命令:jad switchDemoString.class
public class switchDemoString{ public switchDemoString() { } public static void main(String args[]) { String str = "world"; String s; switch((s = str).hashCode(
看,这个代码你肯定看的懂,因为这不就是标准的java的源代码么。这个就很清楚的可以看到原来字符串的switch是通过equals()和hashCode()⽅法来实现的。
但是,jad已经很久不更新了,在对Java7⽣成的字节码进⾏反编译时,偶尔会出现不⽀持的问题,在对Java 8的lambda表达式反编译时就
彻底失败,⽐如会直接
CRF
jad很好⽤,但是⽆奈的是很久没更新了,所以只能⽤⼀款新的⼯具替代他,CFR是⼀个不错的选择,相⽐jad来说,他的语法可能会稍微复
杂⼀些,但是好在他可以work。lambda编程
如,我们使⽤cfr对刚刚的代码进⾏反编译。执⾏⼀下命令:
java -jar cfr_0_125.jar switchDemoString.class --decodestringswitch false
得到以下代码:
public class switchDemoString { public static void main(String[] arrstring) { String string; String string2 = string = "world"; int n = -1; switch (string2.hashCod
通过这段代码也能得到字符串的switch是通过equals()和hashCode()⽅法来实现的结论。
相⽐Jad来说,CFR有很多参数,还是刚刚的代码,如果我们使⽤以下命令,输出结果就会不同:
java -jar cfr_0_125.jar switchDemoString.classpublic class switchDemoString { public static void main(String[] arrstring) { String string; switch (string = "wor
所以--decodestringswitch表⽰对于switch⽀持string的细节进⾏解码。类似的还有--decodeenumswitch、--decodefinally、--decodelambdas等。在我的关于语法糖的⽂章中,我使⽤--decodelambdas对lambda表达式警进⾏了反编译。 源码:
public static void args) { List strList = ImmutableList.of strList.forEach( s -> { System.out.println(s); } );
java -jar cfr_0_125.jar lambdaDemo.class --decodelambdas false反编译后代码:
public static /* varargs */ void main(String ... args) { ImmutableList strList = ImmutableList.of((Object)"Hollis
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论