天天看點

Kotlin-20-檢視Kotlin編譯成class後代碼的三種方式

目錄

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
Kotlin-20-檢視Kotlin編譯成class後代碼的三種方式
第二步:點選左上角的 Decompile 按鈕就會彈出你想要的class源碼
Kotlin-20-檢視Kotlin編譯成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--自己的包名 内
Kotlin-20-檢視Kotlin編譯成class後代碼的三種方式

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檔案

Kotlin-20-檢視Kotlin編譯成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位址,可以按照自己喜歡的方式安裝并檢視功能文檔:

https://github.com/skylot/jadx

下載下傳zip包解壓後,檔案目錄如下:

Kotlin-20-檢視Kotlin編譯成class後代碼的三種方式

輕按兩下jadx-gui就可以打開圖形界面:

Kotlin-20-檢視Kotlin編譯成class後代碼的三種方式
工具支援apk、dex、jar、aar等格式的檔案,可以通用File - Open file選擇檔案或者直接将檔案拖進視窗中,可以算得上一鍵反編譯了,非常簡單易用,對比dex2jar & jd-gui組合,完勝。

AndroidStudio寫的每個class或者kotlin檔案都會編譯成單獨的dex。圖中紅色框 0 是java代碼, 1 是kotlin代碼,我們可以将這些dex直接拖入到jadx反編譯工具中檢視。

Kotlin-20-檢視Kotlin編譯成class後代碼的三種方式

下圖是随手丢進去的一個apk,可以看到不止代碼, 包中的資源也被解出來了。

Kotlin-20-檢視Kotlin編譯成class後代碼的三種方式

繼續閱讀