Kotlin: 發佈 Release 包前優化 Java 字節碼

Kotlin 中刪除了大量須要咱們手寫或者由 IDE 、第三方框架生成的模板代碼。最好的例子就是 Kotlin 是空安全的,因爲這個特性,咱們不須要寫空判斷語句 if(value != null) ,這是 Kotlin/JVM 中額外添加在 Java 字節碼中實現的。因此說好的功能必然須要付出必定的代價來換取。java

下面讓咱們一塊兒來看看 Kotlin 編譯後的字節碼,並學習如何下降這種代價。android

函數參數

示例代碼:git

// Sample.kt
fun sample(arg1: String) {
}
複製代碼

編譯後的 Java 字節碼:github

public final class SampleKt { 
     public static final void sample(@NotNull String arg1) {
        Intrinsics.checkParameterIsNotNull(arg1, 「arg1」);
     }
}
複製代碼

在上面的字節碼中,能夠看到調用了 kotlin.jvm.internal.Intrinsics 類中的 checkParameterIsNotNull 方法進行空檢查。可是實際上咱們是否都須要這些代碼呢?讓咱們看下另外一個例子。安全

平臺類型

Kotlin 中有特定的 types—[platform type](http://platform type/)。你不能聲明這些類型,只能經過其它代碼返回。bash

// Utils.java
public class Utils {

    public static String getValue() {
        throw new RuntimeException();
    }
}
// Sample.kt
fun sample() {
    val value: String = Utils.getValue()
}
複製代碼

編譯後的字節碼:框架

public final class SampleKt {
   public static final void sample() {
      Intrinsics.checkExpressionValueIsNotNull(
         Utils.getValue(), "Utils.getValue()"
      );
   }
}
複製代碼

能夠看到字節碼很是精簡,若是咱們能將開發期間寫的調試代碼在 Release 版本中進行移除,這個特性確定很實用。jvm

移除代碼

ProGuard/R8

你能夠在你的 ProGuard 文件中添加下面的混淆配置來移除工具類的字節碼。ide

// proguard.pro
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
    public static void checkExpressionValueIsNotNull(...);
    public static void checkNotNullExpressionValue(...);
    public static void checkReturnedValueIsNotNull(...);
    public static void checkFieldIsNotNull(...);
    public static void checkParameterIsNotNull(...);
}
複製代碼

-assumenosideeffects 須要你本身保證你所選擇的類的方法沒有邊界效應(簡單來講就是刪掉也不會影響程序運行),而後 proguard 會幫你刪掉這些方法的調用。函數

Kotlin 編譯參數

經過 kotlin 編譯參數配置能夠刪除一些 assert

  • -Xno-call-assertions:不對 platform types 的參數生成空檢查
  • -Xno-receiver-assertions:不對 platform types 的接收參數生成空檢查
  • -Xno-param-assertions:不對 Java 方法參數生成非空檢查
// build.gradle
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile)
    .all {
        kotlinOptions {
            freeCompilerArgs += [
                    '-Xno-call-assertions',
                    '-Xno-receiver-assertions',
                    '-Xno-param-assertions'
            ]
        }
    }
複製代碼

你能夠在這裏查看更多關於 Kotlin/JVM 的編譯參數信息。

總結

Kotlin 是一門很棒的開發語言,儘管它的一些特性支持須要一些代價。可是那些說 Java 沒有添加太多額外字節碼的操做,而 Kotlin 添加不少的說法是愚蠢的。例如 Java 中的特性(泛型和 switch 支持 String)都是經過生成其它的字節碼實現的。Kotlin 生成更多的附加字節碼,所以您在源代碼中寫的更少。

同時,你能夠經過 ProGuard/R8 下降這些影響。我建議在發佈版本時使用這兩種方法。爲何只針對發佈版本?由於高質量的 Android 應用程序必須速度快,每秒 60 幀,並且體積小。但僅限於終端用戶,不要從調試版本中刪除任何內容,以得到儘量多的有關應用程序錯誤行爲的信息,從而簡化應用程序的調試。

相關文章
相關標籤/搜索