Android D8 编译器 和 R8 工具,android 零基础开发
1.3 Android Studio 3.4 版本 D8 R8 变更
在 Android Studio 3.4
版本中,R8
把 desugaring
、shrinking
、obfuscating
、optimizing
和 dexing
都合并到一步进行执行。在 Android Studio 3.4
以前的版本编译流程如下:
合并之后编译流程如下:
注意,如果我们在 build.gradle
中配置了 useProguard = false
则不管是否开启 R8
编译都会使用 R8
进行压缩代码。
2. 脱糖
Android Studio
为使用部分 Java 8
语言功能及利用这些功能的第三方库提供内置支持。默认工具链对 javac
编译器的输出执行字节码转换(称为 desugar
),从而实现新语言功能。
脱糖即在编译阶段将在语法层面一些底层字节码不支持的特性转换为基础的字节码结构,(比如 List
上的泛型脱糖后在字节码层面实际为 Object
); Android
工具链对 Java8
语法特性脱糖的过程可谓丰富多彩,当然他们的最终目的是一致的:使新的语法可以在所有的设备上运行。
经过上面 D8
、R8
的了解,D8
已经支持脱糖,让 Java 8
提供的特性(如 lambdas
)可以转换成 Java 7
特性。把脱糖步骤集成进 D8
影响了所有读或写 .class
字节码的开发工具,因为它会使用 Java 8
格式。可以在 gradle.properties
中禁用脱糖。
android.enableIncrementalDesugaring=false.android.enableDesugar=false
2.1 Lambda 表达式
Java 8
中一个重大变更是引入 Lambda
表达式。
public class Lambda {public static void main(String[] args) {logDebug(msg-> System.out.println(msg), "HelloWorld");}
static void logDebug(Logger logger, String msg) {logger.log(msg);}
@FunctionalInterfaceinterface Logger {void log(String msg);}}
通过 javac
指令将上面的 Lambda.java
转换为字节码。
$javac Lambda.java
接下来通过 javap -v
指令查看字节码的详细内容:
dengshiweideMacBook-Pro:Desktop dengshiwei javap -v Lambda.classClassfile /Users/dengshiwei/Desktop/Lambda.classLast modified 2019-5-12; size 1120 bytesMD5 checksum 67301305720e60d4ef1ff286769768e6Compiled from "Lambda.java"public class Lambdaminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPERConstant pool:#1 = Methodref #9.#25 // java/lang/Object."<init>":()V#2 = InvokeDynamic #0:#30 // #0:log:()LLambdaLogger;#3 = String #31 // HelloWorld#4 = Methodref #8.#32 // Lambda.logDebug:(LLambdaLogger;Ljava/lang/String;)V#5 = InterfaceMethodref #10.#33 // LambdaLogger.log:(Ljava/lang/String;)V#6 = Fieldref #34.#35 // java/lang/System.out:Ljava/io/PrintStream;#7 = Methodref #36.#37 // java/io/PrintStream.println:(Ljava/lang/String;)V#8 = Class #38 // Lambda#9 = Class #39 // java/lang/Object#10 = Class #40 // LambdaLogger#11 = Utf8 Logger#12 = Utf8 InnerClasses#13 = Utf8 <init>#14 = Utf8 ()V#15 = Utf8 Code#16 = Utf8 LineNumberTable#17 = Utf8 main#18 = Utf8 ([Ljava/lang/String;)V#19 = Utf8 logDebug#20 = Utf8 (LLambdaLogger;Ljava/lang/String;)V#21 = Utf8 lambda0#22 = Utf8 (Ljava/lang/String;)V#23 = Utf8 SourceFile#24 = Utf8 Lambda.java#25 = NameAndType #13:#14 // "<init>":()V#26 = Utf8 BootstrapMethods#27 = MethodHandle #6:#41 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandlesLookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;#28 = MethodType #22 // (Ljava/lang/String;)V#29 = MethodHandle #6:#42 // invokestatic Lambda.lambdamain0:(Ljava/lang/String;)V#30 = NameAndType #43:#44 // log:()LLambdaLogger;#31 = Utf8
#32 = NameAndType #19:#20 // logDebug:(LLambdaLogger;Ljava/lang/String;)V#33 = NameAndType #43:#22 // log:(Ljava/lang/String;)V#34 = Class #45 // java/lang/System#35 = NameAndType #46:#47 // out:Ljava/io/PrintStream;#36 = Class #48 // java/io/PrintStream#37 = NameAndType #49:#22 // println:(Ljava/lang/String;)V#38 = Utf8 Lambda#39 = Utf8 java/lang/Object#40 = Utf8 LambdaLogger#41 = Methodref #50.#51 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandlesLookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;#42 = Methodref #8.#52 // Lambda.lambdamain0:(Ljava/lang/String;)V#43 = Utf8 log#44 = Utf8 ()LLambdaLogger;#45 = Utf8 java/lang/System#46 = Utf8 out#47 = Utf8 Ljava/io/PrintStream;#48 = Utf8 java/io/PrintStream#49 = Utf8 println#50 = Class #53 // java/lang/invoke/LambdaMetafactory#51 = NameAndType #54:#57 // metafactory:(Ljava/lang/invoke/MethodHandlesLookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;#52 = NameAndType #21:#22 // lambdamain0:(Ljava/lang/String;)V#53 = Utf8 java/lang/invoke/LambdaMetafactory#54 = Utf8 metafactory#55 = Class #59 // java/lang/invoke/MethodHandlesLookup#56 = Utf8 Lookup#57 = Utf8 (Ljava/lang/invoke/MethodHandlesLookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;#58 = Class #60 // java/lang/invoke/MethodHandles#59 = Utf8 java/lang/invoke/MethodHandlesLookup#60 = Utf8 java/lang/invoke/MethodHandles{public Lambda();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 1: 0
public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=1, args_size=10: invokedynamic #2, 0 // InvokeDynamic #0:log:()LLambdaLogger;5: ldc #3 // String HelloWorld7: invokestatic #4 // Method logDebug:(LLambdaLogger;Ljava/lang/String;)V10: returnLineNumberTable:line 3: 0line 4: 10
static void logDebug(LambdaLogger;Ljava/lang/String;)Vflags: ACC_STATICCode:stack=2, locals=2, args_size=20: aload_01: aload_12: invokeinterface #5, 2 // InterfaceMethod LambdaLogger.log:(Ljava/lang/String;)V7: returnLineNumberTable:line 7: 0line 8: 7}SourceFile: "Lambda.java"InnerClasses:static #11= #10 of #8; //Logger=class LambdaLogger of class Lambdapublic static final #56= #55 of #58; //Lookup=class java/lang/invoke/MethodHandlesLookup of class java/lang/invoke/MethodHandlesBootstrapMethods:0: #27 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandlesLookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
评论