目录
1、方法一
1.1、在AndroidStudio中查看
1.2、样码
1.3、输出结果(简单易读)
2、方法二
2.1、kotlin编译成class所在目录
2.2、Kotlin样码
2.3、注意
2.4、Javap -public 输出结果
2.5、javap -p -private
2.6、Javap -c 输出结果
3、方法三
3.1、Jadx反编译工具
1、方法一
1.1、在AndroidStudio中查看
第一步:选择你要查看你的kotlin文件,然后点击Tools-->Kotlin-->Show Kotlin Bytecode
第二步:点击左上角的 Decompile 按钮就会弹出你想要的class源码
1.2、样码
class TestMain {
public val msg1 = "类中的变量"
private val msg2 = "类中的变量"
companion object {
val msg3 = "伴生对象的变量"
}
}
val msg4 = "Kotlin文件中的变量"
fun sayHello(msg: String) {
println("msg=$msg")
}
fun main() {
val msg5 = "我要看你的class文件"
sayHello(msg5)
}
1.3、输出结果(简单易读)
public final class TestMainKt {
@NotNull
private static final String msg4 = "Kotlin文件中的变量";
@NotNull
public static final String getMsg4() {
return msg4;
}
public static final void sayHello(@NotNull String msg) {
Intrinsics.checkParameterIsNotNull(msg, "msg");
String var1 = "msg=" + msg;
boolean var2 = false;
System.out.println(var1);
}
public static final void main() {
String msg5 = "我要看你的class文件";
sayHello(msg5);
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
}
2、方法二
利用命令行 javap [option] *.class
子命令 | 输出信息 |
-l | 输出行和变量的表 |
-public | 只输出公共的方法和成员 |
-protected | 只输出public和protected类和成员 |
-package | 只输出包,public和protected类和成员,这是默认情况 |
-p -private | 输出所有类和成员 |
-s | 输出内部类型签名 |
-c | 对代码进行反汇编。 eg:类中每一个方法内,包含 java 字节码的指令 |
-verbose | 输出栈大小,方法参数的个数 |
-costants | 输出静态 final 常量 |
2.1、kotlin编译成class所在目录
编译后的class文件在app--tmp--kotlin-classes--自己的包名 内
2.2、Kotlin样码
class TestMain {
public val msg1 = "类中的变量"
private val msg2 = "类中的变量"
companion object {
val msg3 = "伴生对象的变量"
}
}
val msg4 = "Kotlin文件中的变量"
fun sayHello(msg: String) {
println("msg=$msg")
}
fun main() {
val msg5 = "我要看你的class文件"
sayHello(msg5)
}
2.3、注意
在这里需要注意,但我们在一个Kotlin文件中定义了一个类和类外部的一些变量和方法的时候,它在编译后会生成两个class文件。
如下:一个TestMain的类class ,还有一个是TestMainKt.class文件
2.4、Javap -public 输出结果
Javap -public 输出公共的方法和成员
这里分别输出了上面TestMain.kt文件生成的两个class文件的公共的方法和成员变量
javap -public TestMainKt.class
Compiled from "TestMain.kt"
public final class com.yobo.yobo_kotlin.TestMainKt {
public static final java.lang.String getMsg2();
public static final void sayHello(java.lang.String);
public static final void main();
public static void main(java.lang.String[]);
}
javap -public TestMain.class
Compiled from "TestMain.kt"
public final class com.yobo.yobo_kotlin.TestMain {
public static final com.yobo.yobo_kotlin.TestMain$Companion Companion;
public final java.lang.String getMsg1();
public com.yobo.yobo_kotlin.TestMain();
public static final java.lang.String access$getMsg3$cp();
}
2.5、javap -p -private
javap -p -private 显示所有的类和成员
javap -p -private TestMainKt.class
public final class com.yobo.yobo_kotlin.TestMainKt {
private static final java.lang.String msg4;
public static final java.lang.String getMsg4();
public static final void sayHello(java.lang.String);
public static final void main();
public static void main(java.lang.String[]);
static {};
}
2.6、Javap -c 输出结果
Javap -c 对代码进行反汇编。 eg:类中每一个方法内,包含 java 字节码的
可以看到虽然是把我们整个class文件进行了反编译,但是可读性不是很好,这时候我们就推荐第二种方法。
public final class com.yobo.yobo_kotlin.TestMainKt {
public static final java.lang.String getMsg2();
Code:
0: getstatic #13 // Field msg2:Ljava/lang/String;
3: areturn
public static final void sayHello(java.lang.String);
Code:
0: aload_0
1: ldc #17 // String msg
3: invokestatic #23 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: new #25 // class java/lang/StringBuilder
9: dup
10: invokespecial #29 // Method java/lang/StringBuilder."<init>":()V
13: ldc #31 // String msg=
15: invokevirtual #35 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: aload_0
19: invokevirtual #35 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: invokevirtual #38 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: astore_1
26: iconst_0
27: istore_2
28: getstatic #44 // Field java/lang/System.out:Ljava/io/PrintStream;
31: aload_1
32: invokevirtual #50 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
35: return
public static final void main();
Code:
0: ldc #56 // String 我要看你的class文件
2: astore_0
3: aload_0
4: invokestatic #58 // Method sayHello:(Ljava/lang/String;)V
7: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #54 // Method main:()V
3: return
static {};
Code:
0: ldc #8 // String Kotlin文件中的变量
2: putstatic #13 // Field msg2:Ljava/lang/String;
5: return
}
3、方法三
3.1、Jadx反编译工具
先给出工具的GitHub地址,可以按照自己喜欢的方式安装并查看功能文档:
下载zip包解压后,文件目录如下:
双击jadx-gui就可以打开图形界面:
工具支持apk、dex、jar、aar等格式的文件,可以通用File - Open file选择文件或者直接将文件拖进窗口中,可以算得上一键反编译了,非常简单易用,对比dex2jar & jd-gui组合,完胜。
AndroidStudio写的每个class或者kotlin文件都会编译成单独的dex。图中红色框 0 是java代码, 1 是kotlin代码,我们可以将这些dex直接拖入到jadx反编译工具中查看。
下图是随手丢进去的一个apk,可以看到不止代码, 包中的资源也被解出来了。