Copyright©stonee
反编译对了解Java语法糖很有帮助
本文没有写与eclipse或者idea相对应的插件,因为本文的目的是为了了解语法糖,而集成开发环境中的反编译插件有时候并不能直观地显示出编译器语法糖的特点
- 先放上一段源码便于下面的解释
public class tesst{
public static void main(String[] args) {
String string = "world";
switch (string){
case "hello":
System.out.println(string);
break;
case "world":
System.out.println(string);
break;
default:
break;
}
}
}
javap
javap
是jdk自带的一个工具,可以对代码反编译,也可以查看java编译器生成的字节码
- 常用的命令是
javap -c E:\Codes\Java\IdeaProjects\testt\"
用来输出字节码
public class testt.tesst {
public testt.tesst();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String world
2: astore_1
3: aload_1
4: astore_2
5: iconst_m1
6: istore_3
7: aload_2
8: invokevirtual #3 // Method java/lang/:()I
11: lookupswitch { // 2
99162322: 36
113318802: 50
default: 61
}
36: aload_2
37: ldc #4 // String hello
39: invokevirtual #5 // Method java/lang/:(Ljava/lang/Object;)Z
42: ifeq 61
45: iconst_0
46: istore_3
47: goto 61
50: aload_2
51: ldc #2 // String world
53: invokevirtual #5 // Method java/lang/:(Ljava/lang/Object;)Z
56: ifeq 61
59: iconst_1
60: istore_3
61: iload_3
62: lookupswitch { // 2
0: 88
1: 98
default: 108
}
88: getstatic #6 // Field java/lang/:Ljava/io/PrintStream;
91: aload_1
92: invokevirtual #7 // Method java/io/:(Ljava/lang/String;)V
95: goto 108
98: getstatic #6 // Field java/lang/:Ljava/io/PrintStream;
101: aload_1
102: invokevirtual #7 // Method java/io/:(Ljava/lang/String;)V
105: goto 108
108: return
}
- 默认是
javap -package E:\Codes\Java\IdeaProjects\testt\"
输出包名
public class testt.tesst {
public testt.tesst();
public static void main(java.lang.String[]);
}
- 可查阅
javap --help
Jad
Jad是一款用c++写的针对于Java的反编译工具,相对来说比较好用但是好久没有更新了,不支持Java8的新特性
要先进入jad的安装目录
- 常用命令
D:\Decompiler> E:\Codes\Java\IdeaProjects\testt\
之后会在安装目录生成一个jad文件,用文本编辑器打开就可以看到反编译程序了
- 键入
D:\Decompiler>
可获得其他命令
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: /
// Decompiler options: packimports(3)
// Source File Name:
package testt;
import java.io.PrintStream;
public class tesst
{
public tesst()
{
}
public static void main(String args[])
{
String string = "world";
String s = string;
byte byte0 = -1;
switch(s.hashCode())
{
case 99162322:
if(s.equals("hello"))
byte0 = 0;
break;
case 113318802:
if(s.equals("world"))
byte0 = 1;
break;
}
switch(byte0)
{
case 0: // '\0'
System.out.println(string);
break;
case 1: // '\001'
System.out.println(string);
break;
}
}
}
Crf
crf是用java写的一款支持java8特性的反编译工具,常用命令如下:
//首先要先进如安装crf的目录中
//反编译stringswitch
D:\Decompiler>cfr-0.144.jar E:\Codes\Java\IdeaProjects\testt\tesst.class --decodestringswitch false --outputdir E://Codes/Java/Class
//反编译lambda
D:\Decompiler>cfr-0.144.jar E:\Codes\Java\IdeaProjects\testt\tesst.class ----decodelambdas false --outputdir E://Codes/Java/Class
//反编译enumswitch
D:\Decompiler>cfr-0.144.jar E:\Codes\Java\IdeaProjects\testt\tesst.class ----decodeenumswitch false --outputdir E://Codes/Java/Class
//反编译finally
D:\Decompiler>cfr-0.144.jar E:\Codes\Java\IdeaProjects\testt\tesst.class ----decodefinally false --outputdir E://Codes/Java/Class
//别的可使用
D:\Decompiler>cfr-0.144.jar --help
//下面是一个栗子:
/*
* Decompiled with CFR 0.144.
*/
package testt;
import java.io.PrintStream;
public class tesst {
public static void main(String[] args) {
String string;
String string2 = string = "world";
int n = -1;
switch (string2.hashCode()) {
case 99162322: {
if (!string2.equals("hello")) break;
n = 0;
break;
}
case 113318802: {
if (!string2.equals("world")) break;
n = 1;
}
}
switch (n) {
case 0: {
System.out.println(string);
break;
}
case 1: {
System.out.println(string);
break;
}
}
}
}
- 希望每一步都踏踏实实,希望知道的越来越多:)