剪枝
kotlin
package org.example
fun <T : Any> coalesce(a: T?, b: T?): T? = a ?: b
fun main() {
println(coalesce("one", "two"))
println(coalesce(null, "two"))
}
这段代码比较简单, 对 R8 稍微有点了解的人可能会马上反应过来,这个函数因为过于简单,所以大概率是会被 R8 内联的, 内联以后的代码等效于
go
println("one" ?: "two")
println(null ?: "two")
但实际上我们 r8 处理过之后的代码是这样:


你会发现做的比较激进,不只是做了内联,甚至还帮我们做了 Pruning 说人话就是剪枝
这个概念大家自行搜索关键词学习即可,这里就不展开了。我粗浅的理解就是 剪枝的过程就是帮我们排除那些不可能达到的分支代码,并将其移除
空值检查
kotlin 自带空值检查 这个大家肯定都比较熟悉了
kotlin
fun String.double(): String = this + this
fun coalesce(a: String?, b: String?): String? = a ?: b
fun main(args: Array<String>) {
println(coalesce(null, "two")?.double())
}
未使用 r8时,有多条 kotlin 的空值检查语句
使用 r8 之后
多余的空值检查被去除
java中的空值检查
虽然 java 不像 kotlin 中自带空值检查,但是r8 一样对其有着优化
可以看下这个 first 函数
java
final class Nulls {
public static void main(String[] args) {
System.out.println(first(args));
if (args == null) {
System.out.println("null!");
}
}
public static String first(String[] values) {
if (values == null) throw new NullPointerException("values == null");
return values[0];
}
}
需要额外改一下 rules
arduino
-keep class Nulls {
public static java.lang.String first(java.lang.String[]);
}
可以看下未使用 r8 时的指令

使用 r8 之后的指令

显然使用r8 指令之后的 first 方法显的更为高效,因为 null 的条件语句被后置了 从字节码指令的角度来看 显然是 r8 的指令更为效率了