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 帧,并且体积小。但仅限于终端用户,不要从调试版本中删除任何内容,以得到尽量多的有关应用程序错误行为的信息,从而简化应用程序的调试。

相关文章
相关标签/搜索