Slide 1

Slide 1 text

DIGGING INTO D8 AND R8 @JakeWharton

Slide 2

Slide 2 text

$

Slide 3

Slide 3 text

$ export ANDROID_HOME=/path/to/my/sdk

Slide 4

Slide 4 text

$ export ANDROID_HOME=/path/to/my/sdk
 
 $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

Slide 5

Slide 5 text

$ export ANDROID_HOME=/path/to/my/sdk
 
 $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git Cloning into 'depot_tools'...
 remote: Sending approximately 20.90 MiB ...
 remote: Total 27643 (delta 19810), reused 27643 (delta 19810)
 Receiving objects: 100% (27643/27643), 20.90 MiB | 9.97 MiB/s, done.
 Resolving deltas: 100% (19810/19810), done.

Slide 6

Slide 6 text

$ export ANDROID_HOME=/path/to/my/sdk
 
 $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git Cloning into 'depot_tools'...
 remote: Sending approximately 20.90 MiB ...
 remote: Total 27643 (delta 19810), reused 27643 (delta 19810)
 Receiving objects: 100% (27643/27643), 20.90 MiB | 9.97 MiB/s, done.
 Resolving deltas: 100% (19810/19810), done.
 
 $ export PATH=$PATH:`pwd`/depot_tools

Slide 7

Slide 7 text

$ export ANDROID_HOME=/path/to/my/sdk
 
 $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git Cloning into 'depot_tools'...
 remote: Sending approximately 20.90 MiB ...
 remote: Total 27643 (delta 19810), reused 27643 (delta 19810)
 Receiving objects: 100% (27643/27643), 20.90 MiB | 9.97 MiB/s, done.
 Resolving deltas: 100% (19810/19810), done.
 
 $ export PATH=$PATH:`pwd`/depot_tools
 
 $ git clone https://r8.googlesource.com/r8

Slide 8

Slide 8 text

$ export ANDROID_HOME=/path/to/my/sdk
 
 $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git Cloning into 'depot_tools'...
 remote: Sending approximately 20.90 MiB ...
 remote: Total 27643 (delta 19810), reused 27643 (delta 19810)
 Receiving objects: 100% (27643/27643), 20.90 MiB | 9.97 MiB/s, done.
 Resolving deltas: 100% (19810/19810), done.
 
 $ export PATH=$PATH:`pwd`/depot_tools
 
 $ git clone https://r8.googlesource.com/r8 Cloning into 'r8'...
 remote: Sending approximately 21.71 MiB ...
 remote: Counting objects: 67, done
 remote: Total 56838 (delta 23158), reused 56838 (delta 23158)
 Receiving objects: 100% (56838/56838), 21.71 MiB | 10.21 MiB/s, done.
 Resolving deltas: 100% (23158/23158), done.

Slide 9

Slide 9 text


 $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git Cloning into 'depot_tools'...
 remote: Sending approximately 20.90 MiB ...
 remote: Total 27643 (delta 19810), reused 27643 (delta 19810)
 Receiving objects: 100% (27643/27643), 20.90 MiB | 9.97 MiB/s, done.
 Resolving deltas: 100% (19810/19810), done.
 
 $ export PATH=$PATH:`pwd`/depot_tools
 
 $ git clone https://r8.googlesource.com/r8 Cloning into 'r8'...
 remote: Sending approximately 21.71 MiB ...
 remote: Counting objects: 67, done
 remote: Total 56838 (delta 23158), reused 56838 (delta 23158)
 Receiving objects: 100% (56838/56838), 21.71 MiB | 10.21 MiB/s, done.
 Resolving deltas: 100% (23158/23158), done.
 
 $ cd r8

Slide 10

Slide 10 text

Cloning into 'depot_tools'...
 remote: Sending approximately 20.90 MiB ...
 remote: Total 27643 (delta 19810), reused 27643 (delta 19810)
 Receiving objects: 100% (27643/27643), 20.90 MiB | 9.97 MiB/s, done.
 Resolving deltas: 100% (19810/19810), done.
 
 $ export PATH=$PATH:`pwd`/depot_tools
 
 $ git clone https://r8.googlesource.com/r8 Cloning into 'r8'...
 remote: Sending approximately 21.71 MiB ...
 remote: Counting objects: 67, done
 remote: Total 56838 (delta 23158), reused 56838 (delta 23158)
 Receiving objects: 100% (56838/56838), 21.71 MiB | 10.21 MiB/s, done.
 Resolving deltas: 100% (23158/23158), done.
 
 $ cd r8
 
 $ tools/gradle.py d8 r8

Slide 11

Slide 11 text


 $ git clone https://r8.googlesource.com/r8 Cloning into 'r8'...
 remote: Sending approximately 21.71 MiB ...
 remote: Counting objects: 67, done
 remote: Total 56838 (delta 23158), reused 56838 (delta 23158)
 Receiving objects: 100% (56838/56838), 21.71 MiB | 10.21 MiB/s, done.
 Resolving deltas: 100% (23158/23158), done.
 
 $ cd r8
 
 $ tools/gradle.py d8 r8 (… gradle output removed …)
 :R8
 :D8
 
 BUILD SUCCESSFUL
 
 Total time: 28.471 secs

Slide 12

Slide 12 text

Cloning into 'r8'...
 remote: Sending approximately 21.71 MiB ...
 remote: Counting objects: 67, done
 remote: Total 56838 (delta 23158), reused 56838 (delta 23158)
 Receiving objects: 100% (56838/56838), 21.71 MiB | 10.21 MiB/s, done.
 Resolving deltas: 100% (23158/23158), done.
 
 $ cd r8
 
 $ tools/gradle.py d8 r8 (… gradle output removed …)
 :R8
 :D8
 
 BUILD SUCCESSFUL
 
 Total time: 28.471 secs
 
 $ export R8_HOME=`pwd`

Slide 13

Slide 13 text

dx compilers sources libraries transforms

Slide 14

Slide 14 text

$

Slide 15

Slide 15 text

$ cat Java8.java

Slide 16

Slide 16 text

$ cat Java8.java class Java8 { interface Consumer { void accept(T value); } public static void main(String... args) { load(s -> System.out.println(s)); } private static void load(Consumer c) { c.accept("Hello!"); } }

Slide 17

Slide 17 text

$ cat Java8.java class Java8 { interface Consumer { void accept(T value); }W public static void main(String... args) { load(s -> System.out.println(s)); }X private static void load(Consumer c) { c.accept("Hello!"); }Y }Z
 
 $ javac *.java

Slide 18

Slide 18 text

$ cat Java8.java class Java8 { interface Consumer { void accept(T value); }W public static void main(String... args) { load(s -> System.out.println(s)); }X private static void load(Consumer c) { c.accept("Hello!"); }Y }Z
 
 $ javac *.java
 
 $ ls

Slide 19

Slide 19 text

$ cat Java8.java class Java8 { interface Consumer { void accept(T value); }W public static void main(String... args) { load(s -> System.out.println(s)); }X private static void load(Consumer c) { c.accept("Hello!"); }Y }Z
 
 $ javac *.java
 
 $ ls Java8.java Java8.class Java8$Consumer.class

Slide 20

Slide 20 text

interface Consumer { void accept(T value); }W public static void main(String... args) { load(s -> System.out.println(s)); }X private static void load(Consumer c) { c.accept("Hello!"); }Y }Z
 
 $ javac *.java
 
 $ ls Java8.java Java8.class Java8$Consumer.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dx --dex --output . *.class

Slide 21

Slide 21 text

load(s -> System.out.println(s)); }X private static void load(Consumer c) { c.accept("Hello!"); }Y }Z
 
 $ javac *.java
 
 $ ls Java8.java Java8.class Java8$Consumer.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dx --dex --output . *.class Uncaught translation error: com.android.dx.cf.code.SimException:
 ERROR in Java8.main:([Ljava/lang/String;)V:
 invalid opcode ba - invokedynamic requires --min-sdk-version >= 26
 (currently 13)
 1 error; aborting

Slide 22

Slide 22 text

dx compilers sources libraries transforms

Slide 23

Slide 23 text

Desugar dx compilers sources libraries transforms

Slide 24

Slide 24 text

Desugar dx compilers sources libraries transforms

Slide 25

Slide 25 text

Desugar D8 compilers sources libraries transforms

Slide 26

Slide 26 text

D8 compilers sources libraries transforms Desugar

Slide 27

Slide 27 text

Desugar D8 compilers sources libraries transforms

Slide 28

Slide 28 text

load(s -> System.out.println(s)); }X private static void load(Consumer c) { c.accept("Hello!"); }Y }Z
 
 $ javac *.java
 
 $ ls Java8.java Java8.class Java8$Consumer.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dx --dex --output . *.class Uncaught translation error: com.android.dx.cf.code.SimException:
 ERROR in Java8.main:([Ljava/lang/String;)V:
 invalid opcode ba - invokedynamic requires --min-sdk-version >= 26
 (currently 13)
 1 error; aborting

Slide 29

Slide 29 text

}Z
 
 $ javac *.java
 
 $ ls Java8.java Java8.class Java8$Consumer.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dx --dex --output . *.class Uncaught translation error: com.android.dx.cf.code.SimException:
 ERROR in Java8.main:([Ljava/lang/String;)V:
 invalid opcode ba - invokedynamic requires --min-sdk-version >= 26
 (currently 13)
 1 error; aborting
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class

Slide 30

Slide 30 text


 $ ls Java8.java Java8.class Java8$Consumer.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dx --dex --output . *.class Uncaught translation error: com.android.dx.cf.code.SimException:
 ERROR in Java8.main:([Ljava/lang/String;)V:
 invalid opcode ba - invokedynamic requires --min-sdk-version >= 26
 (currently 13)
 1 error; aborting
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ ls Java8.java Java8.class Java8$Consumer.class classes.dex

Slide 31

Slide 31 text

Java8.java Java8.class Java8$Consumer.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dx --dex --output . *.class Uncaught translation error: com.android.dx.cf.code.SimException:
 ERROR in Java8.main:([Ljava/lang/String;)V:
 invalid opcode ba - invokedynamic requires --min-sdk-version >= 26
 (currently 13)
 1 error; aborting
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ ls Java8.java Java8.class Java8$Consumer.class classes.dex $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 32

Slide 32 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex Class #0 - Class descriptor : 'LJava8$Consumer;' Access flags : 0x0600 (INTERFACE ABSTRACT) Superclass : 'Ljava/lang/Object;' Interfaces - Static fields - Instance fields - Direct methods - Virtual methods - #0 : (in LJava8$Consumer;) name : 'accept' type : '(Ljava/lang/Object;)V' access : 0x0401 (PUBLIC ABSTRACT) code : (none) source_file_idx : 14 (Lambda.java) Class #1 - Class descriptor : 'LJava8;' Access flags : 0x0000 () Superclass : 'Ljava/lang/Object;' Interfaces - Static fields - Instance fields - Direct methods - #0 : (in LJava8;) name : '' type : '()V' access : 0x10000 (CONSTRUCTOR) code - registers : 1 ins : 1 outs : 1 insns size : 4 16-bit code units 000288: |[000288] Java8.:()V 000298: 7010 0900 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.:()V // method@0009 00029e: 0e00 |0003: return-void catches : (none) positions : 0x0000 line=1 locals : 0x0000 - 0x0004 reg=0 this LJava8; #1 : (in LJava8;) name : 'lambda$main$0' type : '(Ljava/lang/String;)V' access : 0x1008 (STATIC SYNTHETIC) code - registers : 2 ins : 1 outs : 2 insns size : 6 16-bit code units 0002a0: |[0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V 0002b0: 6200 0100 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0001 0002b4: 6e20 0800 1000 |0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0008 0002ba: 0e00 |0005: return-void catches : (none) positions : 0x0000 line=7 locals : #2 : (in LJava8;) name : 'load' type : '(LJava8$Consumer;)V' access : 0x0009 (PUBLIC STATIC) code - registers : 2 ins : 1 outs : 2 insns size : 6 16-bit code units 0002bc: |[0002bc] Java8.load:(LJava8$Consumer;)V 0002cc: 1a00 0800 |0000: const-string v0, "Hello!" // string@0008 0002d0: 7220 0300 0100 |0002: invoke-interface {v1, v0}, LJava8$Consumer;.accept:(Ljava/lang/Object;)V // method@0003 0002d6: 0e00 |0005: return-void catches : (none) positions : 0x0002 line=13 locals : #3 : (in LJava8;) name : 'main' type : '([Ljava/lang/String;)V' access : 0x0089 (PUBLIC STATIC VARARGS) code - registers : 1 ins : 1 outs : 1 insns size : 6 16-bit code units 0002d8: |[0002d8] Java8.main:([Ljava/lang/String;)V 0002e8: 6200 0000 |0000: sget-object v0, L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;.INSTANCE:L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA; // field@0000 0002ec: 7110 0600 0000 |0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V // method@0006 0002f2: 0e00 |0005: return-void catches : (none) positions : 0x0000 line=7 locals : Virtual methods - source_file_idx : 14 (Lambda.java) Class #2 - Class descriptor : 'L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;' Access flags : 0x1011 (PUBLIC FINAL SYNTHETIC) Superclass : 'Ljava/lang/Object;' Interfaces - #0 : 'LJava8$Consumer;' Static fields - #0 : (in L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;) name : 'INSTANCE' type : 'L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;' access : 0x1019 (PUBLIC STATIC FINAL SYNTHETIC) Instance fields - Direct methods - #0 : (in L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;) name : '' type : '()V' access : 0x11008 (STATIC SYNTHETIC CONSTRUCTOR) code - registers : 1 ins : 0 outs : 1 insns size : 8 16-bit code units 000234: |[000234] -..Lambda.Java8.ZLMFZvUeLmahhYBQbdt-2RNqTMA.:()V 000244: 2200 0000 |0000: new-instance v0, L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA; // type@0000 000248: 7010 0100 0000 |0002: invoke-direct {v0}, L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;.:()V // method@0001 00024e: 6900 0000 |0005: sput-object v0, L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;.INSTANCE:L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA; // field@0000 000252: 0e00 |0007: return-void catches : (none) positions : locals : #1 : (in L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;) name : '' type : '()V' access : 0x11002 (PRIVATE SYNTHETIC CONSTRUCTOR) code - registers : 1 ins : 1 outs : 1 insns size : 4 16-bit code units 000254: |[000254] -..Lambda.Java8.ZLMFZvUeLmahhYBQbdt-2RNqTMA.:()V 000264: 7010 0900 0000 |0000: invoke-direct {v0}, Ljava/lang/Object;.:()V // method@0009 00026a: 0e00 |0003: return-void catches : (none) positions : locals : Virtual methods - #0 : (in L-$$Lambda$Java8$ZLMFZvUeLmahhYBQbdt-2RNqTMA;) name : 'accept' type : '(Ljava/lang/Object;)V' access : 0x0011 (PUBLIC FINAL) code - registers : 2 ins : 2 outs : 1 insns size : 6 16-bit code units 00026c: |[00026c] -..Lambda.Java8.ZLMFZvUeLmahhYBQbdt-2RNqTMA.accept:(Ljava/lang/Object;)V 00027c: 1f01 0900 |0000: check-cast v1, Ljava/lang/String; // type@0009 000280: 7110 0500 0100 |0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V // method@0005 000286: 0e00 |0005: return-void catches : (none) positions : locals : source_file_idx : 28 (lambda) + /Users/jakew/Library/Android/sdk/build-tools/28.0.2/dexdump -d r8.dex Processing 'r8.dex'... Opened 'r8.dex', DEX version '035' Class #0 - Class descriptor : 'LJava8;' Access flags : 0x0000 () Superclass : 'Ljava/lang/Object;' Interfaces - Static fields - Instance fields - Direct methods - #0 : (in LJava8;) name : 'lambda$main$0' type : '(Ljava/lang/String;)V' access : 0x1008 (STATIC SYNTHETIC) code - registers : 2 ins : 1 outs : 2 insns size : 6 16-bit code units 000120: |[000120] Java8.lambda$main$0:(Ljava/lang/String;)V 000130: 6200 0000 |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000 000134: 6e20 0200 1000 |0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0002 00013a: 0e00 |0005: return-void catches : (none) positions : 0x0000 line=1 locals : #1 : (in LJava8;) name : 'main' type : '([Ljava/lang/String;)V' access : 0x0089 (PUBLIC STATIC VARARGS) code - registers : 1 ins : 1 outs : 1 insns size : 8 16-bit code units 00013c: |[00013c] Java8.main:([Ljava/lang/String;)V 00014c: 1a00 0100 |0000: const-string v0, "Hello!" // string@0001 000150: 1f00 0300 |0002: check-cast v0, Ljava/lang/String; // type@0003 000154: 7110 0000 0000 |0004: invoke-static {v0}, LJava8;.lambda$main$0:(Ljava/lang/String;)V // method@0000 00015a: 0e00 |0007: return-void catches : (none) positions : locals : Virtual methods - source_file_idx : 0 ()

Slide 33

Slide 33 text

Java8.java Java8.class Java8$Consumer.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dx --dex --output . *.class Uncaught translation error: com.android.dx.cf.code.SimException:
 ERROR in Java8.main:([Ljava/lang/String;)V:
 invalid opcode ba - invokedynamic requires --min-sdk-version >= 26
 (currently 13)
 1 error; aborting $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ ls Java8.java Java8.class Java8$Consumer.class classes.dex $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 34

Slide 34 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 35

Slide 35 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 36

Slide 36 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 37

Slide 37 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 38

Slide 38 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 39

Slide 39 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 40

Slide 40 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 41

Slide 41 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 42

Slide 42 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 43

Slide 43 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 44

Slide 44 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002d8] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, LJava8$1;.INSTANCE:LJava8$1;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: return-void
 
 [0002a0] Java8.lambda$main$0:(Ljava/lang/String;)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0005: return-void
 
 [000234] Java8$1.:()V
 0000: new-instance v0, LJava8$1;
 0002: invoke-direct {v0}, LJava8$1;.:()V
 0005: sput-object v0, LJava8$1;.INSTANCE:LJava8;
 0007: return-void
 
 [00026c] Java8$1.accept:(Ljava/lang/Object;)V
 0000: check-cast v1, Ljava/lang/String;
 0002: invoke-static {v1}, LJava8;.lambda$main$0:(Ljava/lang/String;)V
 0005: return-void

Slide 45

Slide 45 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 46

Slide 46 text

class Java8 { public static void main(String... args) { load(s -> lambda$main$0(s)); }X static void lambda$main$0(String s) { System.out.println(s); }A interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 47

Slide 47 text

s -> class Java8$1 implements Consumer { @Override public void accept(String s) { Java8.lambda$main$0(s); }Y }Z class Java8 { public static void main(String... args) { load(new Java8$1()); }X static void lambda$main$0(String s) { System.out.println(s); }A interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 48

Slide 48 text

class Java8$1 implements Consumer { static final Java8$1 INSTANCE = new Java8$1(); @Override public void accept(String s) { Java8.lambda$main$0(s); }Y }Z class Java8 { public static void main(String... args) { load(Java8$1.INSTANCE); }X static void lambda$main$0(String s) { System.out.println(s); }A interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 49

Slide 49 text

class Java8$1 implements Consumer { static final Java8$1 INSTANCE = new Java8$1(); @Override public void accept(String s) { Java8.lambda$main$0(s); }Y }Z class Java8 { public static void main(String... args) { load(Java8$1.INSTANCE); }X static void lambda$main$0(String s) { System.out.println(s); }A interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 50

Slide 50 text

class -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY implements Consumer { static final -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY INSTANCE = new -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY(); @Override public void accept(String s) { Java8.lambda$main$0(s); }Y }Z class Java8 { public static void main(String... args) { load(-$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY.INSTANCE); }X static void lambda$main$0(String s) { System.out.println(s); }A interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 51

Slide 51 text

class -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY implements Consumer { static final -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY INSTANCE = new -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY(); @Override public void accept(String s) { Java8.lambda$main$0(s); }Y }Z class Java8 { public static void main(String... args) { load(-$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY.INSTANCE); }X static void lambda$main$0(String s) { System.out.println(s); }A interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 52

Slide 52 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 53

Slide 53 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(args[0] + " " + s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 54

Slide 54 text

s -> class -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY implements Consumer { private final String[] args; -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY(String[] args) { this.args = args; } @Override public void accept(String s) { Java8.lambda$main$0(args, s); } } class Java8 { public static void main(String... args) { load(new -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY(args)); }X static void lambda$main$0(String[] args, String s) { System.out.println(args[0] + " " + s); }A interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 55

Slide 55 text

class -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY implements Consumer { private final String[] args; -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY(String[] args) { this.args = args; } @Override public void accept(String s) { Java8.lambda$main$0(args, s); } } class Lambda { public static void main(String... args) { load(new -$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY(args)); }X static void lambda$main$0(String[] args, String s) { System.out.println(args[0] + " " + s); }A interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 56

Slide 56 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 57

Slide 57 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(s)); // other code… load(s -> System.out.println(s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 58

Slide 58 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(s)); // other code… load(s -> System.out.println(s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java

Slide 59

Slide 59 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(s)); // other code… load(s -> System.out.println(s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class

Slide 60

Slide 60 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(s)); // other code… load(s -> System.out.println(s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 61

Slide 61 text

private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [00039c] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, L-$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY;.INSTANCE
 :L-$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: sget-object v0, L-$$Lambda$Java8$6t081pcxeVAk2jXN7bDL1QxzIIU;.INSTANCE
 :L-$$Lambda$Java8$6t081pcxeVAk2jXN7bDL1QxzIIU;
 0007: invoke-static {v0}, LJava;.load:(LJava8$Consumer;)V
 000a: return-void

Slide 62

Slide 62 text

private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [00039c] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v0, L-$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY;.INSTANCE
 :L-$$Lambda$Java8$fcyZxanqBZSHC_nf-noKh-e3bnY;
 0002: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0005: sget-object v0, L-$$Lambda$Java8$6t081pcxeVAk2jXN7bDL1QxzIIU;.INSTANCE
 :L-$$Lambda$Java8$6t081pcxeVAk2jXN7bDL1QxzIIU;
 0007: invoke-static {v0}, LJava;.load:(LJava8$Consumer;)V
 000a: return-void

Slide 63

Slide 63 text

class Java8 { public static void main(String... args) { load(s -> System.out.println(s)); // other code… load(s -> System.out.println(s)); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 64

Slide 64 text

class Java8 { public static void main(String... args) { load(System.out::println); // other code… load(System.out::println); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z

Slide 65

Slide 65 text

class Java8 { public static void main(String... args) { load(System.out::println); // other code… load(System.out::println); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java

Slide 66

Slide 66 text

class Java8 { public static void main(String... args) { load(System.out::println); // other code… load(System.out::println); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class

Slide 67

Slide 67 text

class Java8 { public static void main(String... args) { load(System.out::println); // other code… load(System.out::println); }X interface Consumer { void accept(T value); }W private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 68

Slide 68 text

private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002bc] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 0004: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0007: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 000a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000c: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 000e: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0011: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0014: return-void

Slide 69

Slide 69 text

private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002bc] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 0004: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0007: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 000a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000c: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 000e: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0011: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0014: return-void

Slide 70

Slide 70 text

private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002bc] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 0004: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0007: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 000a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000c: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 000e: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0011: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0014: return-void

Slide 71

Slide 71 text

private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002bc] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 0004: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0007: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 000a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000c: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 000e: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0011: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0014: return-void

Slide 72

Slide 72 text

private static void load(Consumer c) { c.accept("Hello!"); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [0002bc] Java8.main:([Ljava/lang/String;)V
 0000: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 0004: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0007: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 000a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000c: new-instance v0, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;
 000e: invoke-direct {v0, v1}, L-$$Lambda$3a8cOTS_BDddTs3zL5A7slX7lPc;.:(Ljava/io/PrintStream;)V
 0011: invoke-static {v0}, LJava8;.load:(LJava8$Consumer;)V
 0014: return-void

Slide 73

Slide 73 text

$ cat Not.java

Slide 74

Slide 74 text

$ cat Not.java class Not { static void print(int value) { System.out.println(~value); }Y }Z

Slide 75

Slide 75 text

$ cat Not.java class Not { static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java

Slide 76

Slide 76 text

$ cat Not.java class Not { static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class

Slide 77

Slide 77 text

$ cat Not.java class Not { static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 78

Slide 78 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 79

Slide 79 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 80

Slide 80 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 81

Slide 81 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void 00010100 xor 11111111

Slide 82

Slide 82 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void 00010100 xor 11111111 11101011 =

Slide 83

Slide 83 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 84

Slide 84 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 85

Slide 85 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 86

Slide 86 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 87

Slide 87 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 88

Slide 88 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 89

Slide 89 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 90

Slide 90 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 91

Slide 91 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 92

Slide 92 text

static void print(int value) { System.out.println(~value); }Y }Z $ javac *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void

Slide 93

Slide 93 text

$ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class

Slide 94

Slide 94 text

$ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class

Slide 95

Slide 95 text

$ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class

Slide 96

Slide 96 text

--release \
 --output . \
 *.class $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 97

Slide 97 text

[000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: not-int v1, v1
 0003: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0006: return-void

Slide 98

Slide 98 text

[000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: not-int v1, v1
 0003: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0006: return-void

Slide 99

Slide 99 text

[000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: not-int v1, v1
 0003: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0006: return-void

Slide 100

Slide 100 text

[000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: not-int v1, v1
 0003: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0006: return-void

Slide 101

Slide 101 text

[000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: not-int v1, v1
 0003: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0006: return-void

Slide 102

Slide 102 text

[000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: not-int v1, v1
 0003: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0006: return-void

Slide 103

Slide 103 text

[000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: xor-int/lit8 v1, v1, #int -1
 0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0007: return-void
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --min-api 21
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000134] Not.print:(I)V
 0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0002: not-int v1, v1
 0003: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V
 0006: return-void

Slide 104

Slide 104 text

D8 compilers sources libraries transforms

Slide 105

Slide 105 text

ProGuard D8 compilers sources libraries transforms

Slide 106

Slide 106 text

D8 compilers sources libraries transforms ProGuard

Slide 107

Slide 107 text

ProGuard compilers sources libraries transforms R8

Slide 108

Slide 108 text

$ cat Greeter.kt

Slide 109

Slide 109 text

$ cat Greeter.kt fun main(vararg args: String) { println(Greeter.hello("Droidcon")) } class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) } }

Slide 110

Slide 110 text

$ cat Greeter.kt fun main(vararg args: String) { println(Greeter.hello("Droidcon")) } class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) } }

Slide 111

Slide 111 text

$ cat Greeter.kt fun main(vararg args: String) { println(Greeter.hello("Droidcon")) } class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) } }

Slide 112

Slide 112 text

$ cat Greeter.kt fun main(vararg args: String) { println(Greeter.hello("Droidcon")) } class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) } }

Slide 113

Slide 113 text

$ cat Greeter.kt fun main(vararg args: String) { println(Greeter.hello("Droidcon")) } class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) } }

Slide 114

Slide 114 text

$ cat Greeter.kt fun main(vararg args: String) { println(Greeter.hello("Droidcon")) }Z class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) }Y }Z
 
 $ kotlinc -classpath $ANDROID_HOME/platforms/android-28/android.jar *.kt

Slide 115

Slide 115 text

fun main(vararg args: String) { println(Greeter.hello("Droidcon")) }Z class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) }Y }Z
 
 $ kotlinc -classpath $ANDROID_HOME/platforms/android-28/android.jar *.kt
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class

Slide 116

Slide 116 text

println(Greeter.hello("Droidcon")) }Z class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) }Y }Z
 
 $ kotlinc -classpath $ANDROID_HOME/platforms/android-28/android.jar *.kt
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 117

Slide 117 text

--lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 [000314] Greeter.Companion.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3

Slide 118

Slide 118 text

--lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 [000314] Greeter.Companion.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3

Slide 119

Slide 119 text

--lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 [000314] Greeter.Companion.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3

Slide 120

Slide 120 text

--lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 [000314] Greeter.Companion.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3

Slide 121

Slide 121 text

--output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 [000314] Greeter.Companion.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3
 
 $ cat rules.txt

Slide 122

Slide 122 text

0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 [000314] Greeter.Companion.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate

Slide 123

Slide 123 text

0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class

Slide 124

Slide 124 text

0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class

Slide 125

Slide 125 text

0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class

Slide 126

Slide 126 text

0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class

Slide 127

Slide 127 text

0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v3}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v3
 000b: return-object v3
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 128

Slide 128 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 129

Slide 129 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 130

Slide 130 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 131

Slide 131 text


 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 132

Slide 132 text


 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 133

Slide 133 text


 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 134

Slide 134 text

class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) }B }A

Slide 135

Slide 135 text

class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) }B }A public final class Greeter { public static final Companion Companion = new Companion(); private final String greeting; public Greeter(String greeting) { this.greeting = greeting; } public String getGreeting() { return greeting; } public String greet(String name) { return greeting + ", " + name; } public static final class Companion { private Companion() {} public String hello(String name) { return new Greeter("Hello").greet(name); }X }Y }Z

Slide 136

Slide 136 text

class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) }B }A public final class Greeter { private final String greeting; public Greeter(String greeting) { this.greeting = greeting; } public String getGreeting() { return greeting; } public String greet(String name) { return greeting + ", " + name; } public static String hello(String name) { return new Greeter("Hello").greet(name); }X }Z

Slide 137

Slide 137 text

class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { fun hello(name: String) = Greeter("Hello").greet(name) }B }A

Slide 138

Slide 138 text

class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { @JvmStatic fun hello(name: String) = Greeter("Hello").greet(name) }B }A

Slide 139

Slide 139 text

class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { @JvmStatic fun hello(name: String) = Greeter("Hello").greet(name) } }
 
 $ kotlinc -classpath $ANDROID_HOME/platforms/android-28/android.jar *.kt

Slide 140

Slide 140 text

class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { @JvmStatic fun hello(name: String) = Greeter("Hello").greet(name) }B }A
 
 $ kotlinc -classpath $ANDROID_HOME/platforms/android-28/android.jar *.kt
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class

Slide 141

Slide 141 text

class Greeter(val greeting: String) { fun greet(name: String) = "$greeting, $name!" companion object { @JvmStatic fun hello(name: String) = Greeter("Hello").greet(name) }B }A
 
 $ kotlinc -classpath $ANDROID_HOME/platforms/android-28/android.jar *.kt
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 142

Slide 142 text

--output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 #2 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [00042c] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: sget-object v0, LGreeter;.Companion:LGreeter$Companion;
 0002: invoke-virtual {v0, v1}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: return-object v1

Slide 143

Slide 143 text

--output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 #2 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [00042c] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: sget-object v0, LGreeter;.Companion:LGreeter$Companion;
 0002: invoke-virtual {v0, v1}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: return-object v1

Slide 144

Slide 144 text

--output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 #2 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [00042c] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: sget-object v0, LGreeter;.Companion:LGreeter$Companion;
 0002: invoke-virtual {v0, v1}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: return-object v1

Slide 145

Slide 145 text

--output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 #2 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [00042c] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: sget-object v0, LGreeter;.Companion:LGreeter$Companion;
 0002: invoke-virtual {v0, v1}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: return-object v1

Slide 146

Slide 146 text

--output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000370] GreeterKt.main:([Ljava/lang/String;)V
 0000: sget-object v1, LGreeter;.Companion:LGreeter$Companion;
 0002: const-string v0, "Droidcon"
 0005: invoke-virtual {v1, v0}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 #2 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [00042c] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: sget-object v0, LGreeter;.Companion:LGreeter$Companion;
 0002: invoke-virtual {v0, v1}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: return-object v1

Slide 147

Slide 147 text

0008: move-result-object v1
 0009: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 #2 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [00042c] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: sget-object v0, LGreeter;.Companion:LGreeter$Companion;
 0002: invoke-virtual {v0, v1}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: return-object v1
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class

Slide 148

Slide 148 text

000b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000e: return-void
 
 #2 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [00042c] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: sget-object v0, LGreeter;.Companion:LGreeter$Companion;
 0002: invoke-virtual {v0, v1}, LGreeter$Companion;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: return-object v1
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 149

Slide 149 text


 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 150

Slide 150 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 151

Slide 151 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 152

Slide 152 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000234] GreeterKt.main:([Ljava/lang/String;)V
 0000: const-string v1, "Droidcon" // string@0004
 0002: invoke-static {v1}, LGreeter;.hello:(Ljava/lang/String;)Ljava/lang/String;
 0005: move-result-object v1
 0006: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 000b: return-void
 
 #1 : (in LGreeter;)
 name : 'hello'
 type : '(Ljava/lang/String;)Ljava/lang/String;'
 access : 0x0019 (PUBLIC STATIC FINAL)
 code -
 [0002bc] Greeter.hello:(Ljava/lang/String;)Ljava/lang/String;
 0000: new-instance v0, LGreeter;
 0002: const-string v1, "Hello"
 0004: invoke-direct {v0, v1}, LGreeter;.:(Ljava/lang/String;)V
 0007: invoke-virtual {v0, v2}, LGreeter;.greet:(Ljava/lang/String;)Ljava/lang/String;
 000a: move-result-object v2
 000b: return-object v2

Slide 153

Slide 153 text

@Module object HelloGreeterModule { @Provides fun greeter() = Greeter("Hello") }

Slide 154

Slide 154 text

public final class Thing { public static final Thing INSTANCE = new Thing(); private Thing() { } public void doThing() { // … } }

Slide 155

Slide 155 text

$ cat Nulls.kt

Slide 156

Slide 156 text

$ cat Nulls.kt fun coalesce(a: T?, b: T?): T? = a ?: b fun firstOrSecond(first: String?, second: String): String = coalesce(first, second) ?: throw AssertionError() fun main(vararg args: String) { println(firstOrSecond(null, "two")) println(firstOrSecond("one", "two")) }

Slide 157

Slide 157 text

$ cat Nulls.kt fun coalesce(a: T?, b: T?): T? = a ?: b fun firstOrSecond(first: String?, second: String): String = coalesce(first, second) ?: throw AssertionError() fun main(vararg args: String) { println(firstOrSecond(null, "two")) println(firstOrSecond("one", "two")) }

Slide 158

Slide 158 text

$ cat Nulls.kt fun coalesce(a: T?, b: T?): T? = a ?: b fun firstOrSecond(first: String?, second: String): String = coalesce(first, second) ?: throw AssertionError() fun main(vararg args: String) { println(firstOrSecond(null, "two")) println(firstOrSecond("one", "two")) }

Slide 159

Slide 159 text

$ cat Nulls.kt fun coalesce(a: T?, b: T?): T? = a ?: b fun firstOrSecond(first: String?, second: String): String = coalesce(first, second) ?: throw AssertionError() fun main(vararg args: String) { println(firstOrSecond(null, "two")) println(firstOrSecond("one", "two")) }

Slide 160

Slide 160 text

$ cat Nulls.kt fun coalesce(a: T?, b: T?): T? = a ?: b fun firstOrSecond(first: String?, second: String): String = coalesce(first, second) ?: throw AssertionError() fun main(vararg args: String) { println(firstOrSecond(null, "two")) println(firstOrSecond("one", "two")) }

Slide 161

Slide 161 text

$ cat Nulls.kt fun coalesce(a: T?, b: T?): T? = a ?: b fun firstOrSecond(first: String?, second: String): String = coalesce(first, second) ?: throw AssertionError() fun main(vararg args: String) { println(firstOrSecond(null, "two")) println(firstOrSecond("one", "two")) } Z $ kotlinc -classpath kotlin-stdlib-1.2.61.jar *.kt

Slide 162

Slide 162 text

$ cat Nulls.kt fun coalesce(a: T?, b: T?): T? = a ?: b fun firstOrSecond(first: String?, second: String): String = coalesce(first, second) ?: throw AssertionError() fun main(vararg args: String) { println(firstOrSecond(null, "two")) println(firstOrSecond("one", "two")) } Z $ kotlinc -classpath kotlin-stdlib-1.2.61.jar *.kt $ java -jar $R8_HOME/build/libs/d8.jar \ --lib $ANDROID_HOME/platforms/android-28/android.jar \ --lib kotlin-stdlib-1.2.61.jar \ --release \ --output . \ *.class

Slide 163

Slide 163 text

fun coalesce(a: T?, b: T?): T? = a ?: b fun firstOrSecond(first: String?, second: String): String = coalesce(first, second) ?: throw AssertionError() fun main(vararg args: String) { println(firstOrSecond(null, "two")) println(firstOrSecond("one", "two")) } Z $ kotlinc -classpath kotlin-stdlib-1.2.61.jar *.kt $ java -jar $R8_HOME/build/libs/d8.jar \ --lib $ANDROID_HOME/platforms/android-28/android.jar \ --lib kotlin-stdlib-1.2.61.jar \ --release \ --output . \ *.class 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 164

Slide 164 text

*.class 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000208] NullsKt.coalesce:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 0000: if-eqz v0, 0003
 0002: goto 0004
 0003: move-object v0, v1
 0004: return-object v0
 
 [000224] NullsKt.firstOrSecond:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 0000: const-string v0, "second"
 0002: invoke-static {v2, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: invoke-static {v1, v2}, LNullsKt;.coalesce:(LString;LString;)Ljava/lang/String;
 0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V


Slide 165

Slide 165 text

*.class 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000208] NullsKt.coalesce:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 0000: if-eqz v0, 0003
 0002: goto 0004
 0003: move-object v0, v1
 0004: return-object v0
 
 [000224] NullsKt.firstOrSecond:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 0000: const-string v0, "second"
 0002: invoke-static {v2, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: invoke-static {v1, v2}, LNullsKt;.coalesce:(LString;LString;)Ljava/lang/String;
 0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V


Slide 166

Slide 166 text

*.class 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000208] NullsKt.coalesce:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 0000: if-eqz v0, 0003
 0002: goto 0004
 0003: move-object v0, v1
 0004: return-object v0
 
 [000224] NullsKt.firstOrSecond:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 0000: const-string v0, "second"
 0002: invoke-static {v2, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: invoke-static {v1, v2}, LNullsKt;.coalesce:(LString;LString;)Ljava/lang/String;
 0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V


Slide 167

Slide 167 text

*.class 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000208] NullsKt.coalesce:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 0000: if-eqz v0, 0003
 0002: goto 0004
 0003: move-object v0, v1
 0004: return-object v0
 
 [000224] NullsKt.firstOrSecond:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 0000: const-string v0, "second"
 0002: invoke-static {v2, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: invoke-static {v1, v2}, LNullsKt;.coalesce:(LString;LString;)Ljava/lang/String;
 0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V


Slide 168

Slide 168 text

*.class 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000208] NullsKt.coalesce:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 0000: if-eqz v0, 0003
 0002: goto 0004
 0003: move-object v0, v1
 0004: return-object v0
 
 [000224] NullsKt.firstOrSecond:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 0000: const-string v0, "second"
 0002: invoke-static {v2, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: invoke-static {v1, v2}, LNullsKt;.coalesce:(LString;LString;)Ljava/lang/String;
 0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V


Slide 169

Slide 169 text

0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: const-string v1, "two"
 0007: const/4 v0, #int 0
 0008: invoke-static {v0, v1}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 000b: move-result-object v1
 000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000e: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0011: const-string v1, "one"
 0013: const-string v0, "two"
 0015: invoke-static {v1, v0}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 0018: move-result-object v1
 0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void

Slide 170

Slide 170 text

0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: const-string v1, "two"
 0007: const/4 v0, #int 0
 0008: invoke-static {v0, v1}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 000b: move-result-object v1
 000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000e: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0011: const-string v1, "one"
 0013: const-string v0, "two"
 0015: invoke-static {v1, v0}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 0018: move-result-object v1
 0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void

Slide 171

Slide 171 text

0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: const-string v1, "two"
 0007: const/4 v0, #int 0
 0008: invoke-static {v0, v1}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 000b: move-result-object v1
 000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000e: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0011: const-string v1, "one"
 0013: const-string v0, "two"
 0015: invoke-static {v1, v0}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 0018: move-result-object v1
 0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void

Slide 172

Slide 172 text

0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: const-string v1, "two"
 0007: const/4 v0, #int 0
 0008: invoke-static {v0, v1}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 000b: move-result-object v1
 000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000e: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0011: const-string v1, "one"
 0013: const-string v0, "two"
 0015: invoke-static {v1, v0}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 0018: move-result-object v1
 0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void

Slide 173

Slide 173 text

0008: move-result-object v1
 0009: if-eqz v1, 000c
 000b: return-object v1
 000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: const-string v1, "two"
 0007: const/4 v0, #int 0
 0008: invoke-static {v0, v1}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 000b: move-result-object v1
 000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000e: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0011: const-string v1, "one"
 0013: const-string v0, "two"
 0015: invoke-static {v1, v0}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 0018: move-result-object v1
 0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void

Slide 174

Slide 174 text

000c: new-instance v1, Ljava/lang/AssertionError;
 000e: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V
 0011: check-cast v1, Ljava/lang/Throwable;
 0013: throw v1
 
 [00025c] NullsKt.main:([Ljava/lang/String;)V
 0000: const-string v0, "args"
 0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: const-string v1, "two"
 0007: const/4 v0, #int 0
 0008: invoke-static {v0, v1}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 000b: move-result-object v1
 000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000e: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0011: const-string v1, "one"
 0013: const-string v0, "two"
 0015: invoke-static {v1, v0}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 0018: move-result-object v1
 0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void
 
 $ cat rules.txt

Slide 175

Slide 175 text

0002: invoke-static {v1, v0}, Lkotlin/jvm/internal/Intrinsics;.checkParameterIsNotNull:(…)V
 0005: const-string v1, "two"
 0007: const/4 v0, #int 0
 0008: invoke-static {v0, v1}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 000b: move-result-object v1
 000c: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000e: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0011: const-string v1, "one"
 0013: const-string v0, "two"
 0015: invoke-static {v1, v0}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 0018: move-result-object v1
 0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate -allowaccessmodification

Slide 176

Slide 176 text

0015: invoke-static {v1, v0}, LNullsKt;.firstOrSecond:(LString;LString;)LString;
 0018: move-result-object v1
 0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate -allowaccessmodification $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class kotlin-stdlib-1.2.61.jar

Slide 177

Slide 177 text

0019: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001b: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 001e: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(java.lang.String[]); }Z -dontobfuscate -allowaccessmodification $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class kotlin-stdlib-1.2.61.jar
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 178

Slide 178 text

--release \
 --output . \
 --pg-conf rules.txt \
 *.class kotlin-stdlib-1.2.61.jar
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000314] NullsKt.main:([Ljava/lang/String;)V
 0000: if-eqz v1, 0011
 0002: const-string v1, "two"
 0004: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0006: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0009: const-string v1, "one"
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0010: return-void
 0011: const-string v1, "args"
 0013: invoke-static {v1}, Lkotlin/jvm/internal/Intrinsics;.throwParameterIsNullException:(…)V
 0016: const/4 v1, #int 0
 0017: throw v1
 
 [000354] kotlin.jvm.internal.Intrinsics.throwParameterIsNullException:(Ljava/lang/String;)V
 0000: (lots of bytecodes…)

Slide 179

Slide 179 text

--release \
 --output . \
 --pg-conf rules.txt \
 *.class kotlin-stdlib-1.2.61.jar
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000314] NullsKt.main:([Ljava/lang/String;)V
 0000: if-eqz v1, 0011
 0002: const-string v1, "two"
 0004: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0006: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0009: const-string v1, "one"
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0010: return-void
 0011: const-string v1, "args"
 0013: invoke-static {v1}, Lkotlin/jvm/internal/Intrinsics;.throwParameterIsNullException:(…)V
 0016: const/4 v1, #int 0
 0017: throw v1
 
 [000354] kotlin.jvm.internal.Intrinsics.throwParameterIsNullException:(Ljava/lang/String;)V
 0000: (lots of bytecodes…)

Slide 180

Slide 180 text

--release \
 --output . \
 --pg-conf rules.txt \
 *.class kotlin-stdlib-1.2.61.jar
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000314] NullsKt.main:([Ljava/lang/String;)V
 0000: if-eqz v1, 0011
 0002: const-string v1, "two"
 0004: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0006: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0009: const-string v1, "one"
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0010: return-void
 0011: const-string v1, "args"
 0013: invoke-static {v1}, Lkotlin/jvm/internal/Intrinsics;.throwParameterIsNullException:(…)V
 0016: const/4 v1, #int 0
 0017: throw v1
 
 [000354] kotlin.jvm.internal.Intrinsics.throwParameterIsNullException:(Ljava/lang/String;)V
 0000: (lots of bytecodes…)

Slide 181

Slide 181 text

--release \
 --output . \
 --pg-conf rules.txt \
 *.class kotlin-stdlib-1.2.61.jar
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000314] NullsKt.main:([Ljava/lang/String;)V
 0000: if-eqz v1, 0011
 0002: const-string v1, "two"
 0004: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0006: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0009: const-string v1, "one"
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0010: return-void
 0011: const-string v1, "args"
 0013: invoke-static {v1}, Lkotlin/jvm/internal/Intrinsics;.throwParameterIsNullException:(…)V
 0016: const/4 v1, #int 0
 0017: throw v1
 
 [000354] kotlin.jvm.internal.Intrinsics.throwParameterIsNullException:(Ljava/lang/String;)V
 0000: (lots of bytecodes…)

Slide 182

Slide 182 text

--release \
 --output . \
 --pg-conf rules.txt \
 *.class kotlin-stdlib-1.2.61.jar
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000314] NullsKt.main:([Ljava/lang/String;)V
 0000: if-eqz v1, 0011
 0002: const-string v1, "two"
 0004: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0006: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0009: const-string v1, "one"
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0010: return-void
 0011: const-string v1, "args"
 0013: invoke-static {v1}, Lkotlin/jvm/internal/Intrinsics;.throwParameterIsNullException:(…)V
 0016: const/4 v1, #int 0
 0017: throw v1
 
 [000354] kotlin.jvm.internal.Intrinsics.throwParameterIsNullException:(Ljava/lang/String;)V
 0000: (lots of bytecodes…)

Slide 183

Slide 183 text

--release \
 --output . \
 --pg-conf rules.txt \
 *.class kotlin-stdlib-1.2.61.jar
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000314] NullsKt.main:([Ljava/lang/String;)V
 0000: if-eqz v1, 0011
 0002: const-string v1, "two"
 0004: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0006: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0009: const-string v1, "one"
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/Object;)V
 0010: return-void
 0011: const-string v1, "args"
 0013: invoke-static {v1}, Lkotlin/jvm/internal/Intrinsics;.throwParameterIsNullException:(…)V
 0016: const/4 v1, #int 0
 0017: throw v1
 
 [000354] kotlin.jvm.internal.Intrinsics.throwParameterIsNullException:(Ljava/lang/String;)V
 0000: (lots of bytecodes…)

Slide 184

Slide 184 text

$ cat SdkIntSimple.java

Slide 185

Slide 185 text

$ cat SdkIntSimple.java import android.os.Build; class SdkIntSimple { public static void main(String... args) { if (Build.VERSION.SDK_INT >= 21) { System.out.println("21+"); } else if (Build.VERSION.SDK_INT >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); } } }

Slide 186

Slide 186 text

$ cat SdkIntSimple.java import android.os.Build; class SdkIntSimple { public static void main(String... args) { if (Build.VERSION.SDK_INT >= 21) { System.out.println("21+"); } else if (Build.VERSION.SDK_INT >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z $ javac -bootclasspath $ANDROID_HOME/platforms/android-28/android.jar *.java

Slide 187

Slide 187 text

class SdkIntSimple { public static void main(String... args) { if (Build.VERSION.SDK_INT >= 21) { System.out.println("21+"); } else if (Build.VERSION.SDK_INT >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z $ javac -bootclasspath $ANDROID_HOME/platforms/android-28/android.jar *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class

Slide 188

Slide 188 text

public static void main(String... args) { if (Build.VERSION.SDK_INT >= 21) { System.out.println("21+"); } else if (Build.VERSION.SDK_INT >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z $ javac -bootclasspath $ANDROID_HOME/platforms/android-28/android.jar *.java $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 189

Slide 189 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000170] SdkIntSimple.main:([Ljava/lang/String;)V
 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v0, #int 21
 0004: if-lt v1, v0, 000e
 0006: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: const-string v0, "21+"
 000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void

Slide 190

Slide 190 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000170] SdkIntSimple.main:([Ljava/lang/String;)V
 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v0, #int 21
 0004: if-lt v1, v0, 000e
 0006: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: const-string v0, "21+"
 000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void

Slide 191

Slide 191 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000170] SdkIntSimple.main:([Ljava/lang/String;)V
 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v0, #int 21
 0004: if-lt v1, v0, 000e
 0006: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: const-string v0, "21+"
 000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void

Slide 192

Slide 192 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000170] SdkIntSimple.main:([Ljava/lang/String;)V
 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v0, #int 21
 0004: if-lt v1, v0, 000e
 0006: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: const-string v0, "21+"
 000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void

Slide 193

Slide 193 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000170] SdkIntSimple.main:([Ljava/lang/String;)V
 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v0, #int 21
 0004: if-lt v1, v0, 000e
 0006: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: const-string v0, "21+"
 000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void

Slide 194

Slide 194 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000170] SdkIntSimple.main:([Ljava/lang/String;)V
 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v0, #int 21
 0004: if-lt v1, v0, 000e
 0006: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: const-string v0, "21+"
 000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void

Slide 195

Slide 195 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000170] SdkIntSimple.main:([Ljava/lang/String;)V
 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v0, #int 21
 0004: if-lt v1, v0, 000e
 0006: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: const-string v0, "21+"
 000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void

Slide 196

Slide 196 text

$ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000170] SdkIntSimple.main:([Ljava/lang/String;)V
 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v0, #int 21
 0004: if-lt v1, v0, 000e
 0006: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0008: const-string v0, "21+"
 000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void
 
 $ cat rules.txt

Slide 197

Slide 197 text

000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A

Slide 198

Slide 198 text

000a: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 000d: goto 0023
 000e: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I
 0010: const/16 v0, #int 16
 0012: if-lt v1, v0, 001c
 0014: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 0016: const-string v0, "16+"
 0018: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A

Slide 199

Slide 199 text

001b: goto 0023
 001c: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream;
 001e: const-string v0, "Pre-16"
 0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class

Slide 200

Slide 200 text

0020: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V
 0023: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 201

Slide 201 text

public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000130] SdkIntSimple.main:([Ljava/lang/String;)V 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I 0002: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; 0004: const-string v0, "21+" 0006: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V 0009: return-void

Slide 202

Slide 202 text

public static void main(...);
 } 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000130] SdkIntSimple.main:([Ljava/lang/String;)V 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I 0002: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; 0004: const-string v0, "21+" 0006: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V 0009: return-void

Slide 203

Slide 203 text

public static void main(...);
 } 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000130] SdkIntSimple.main:([Ljava/lang/String;)V 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I 0002: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; 0004: const-string v0, "21+" 0006: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V 0009: return-void

Slide 204

Slide 204 text

public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [000130] SdkIntSimple.main:([Ljava/lang/String;)V 0000: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I 0002: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; 0004: const-string v0, "21+" 0006: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V 0009: return-void

Slide 205

Slide 205 text

class SdkIntSimple { public static void main(String... args) { if (Build.VERSION.SDK_INT >= 21) { System.out.println("21+"); } else if (Build.VERSION.SDK_INT >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z

Slide 206

Slide 206 text

class SdkIntSimple { public static void main(String... args) { if (Build.VERSION.SDK_INT >= 21) { System.out.println("21+"); } else if (Build.VERSION.SDK_INT >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }

Slide 207

Slide 207 text

Build.VERSION.SDK_INT Build.VERSION.SDK_INT class SdkIntSimple { public static void main(String... args) { if ([21..2147483647] >= 21) { System.out.println("21+"); } else if ([21..2147483647] >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }G

Slide 208

Slide 208 text

class SdkIntSimple { public static void main(String... args) { if ([21..2147483647] >= 21) { System.out.println("21+"); } else if ([21..2147483647] >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }G

Slide 209

Slide 209 text

class SdkIntSimple { public static void main(String... args) { if (true) { System.out.println("21+"); } else if ([21..2147483647] >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }G

Slide 210

Slide 210 text

class SdkIntSimple { public static void main(String... args) { if (true) { System.out.println("21+"); } else if ([21..2147483647] >= 16) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }G

Slide 211

Slide 211 text

class SdkIntSimple { public static void main(String... args) { if (true) { System.out.println("21+"); } else if (true) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }G

Slide 212

Slide 212 text

class SdkIntSimple { public static void main(String... args) { if (true) { System.out.println("21+"); } else if (true) { System.out.println("16+"); } else { System.out.println("Pre-16"); }X }Y }Z -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }G

Slide 213

Slide 213 text

class SdkIntSimple { public static void main(String... args) { System.out.println("21+"); }Y }Z -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }G

Slide 214

Slide 214 text

class ViewCompat { static void postOnAnimation(@NonNull View view, Runnable action) { if (Build.VERSION.SDK_INT >= 16) { view.postOnAnimation(action); } else { view.postDelayed(action, ValueAnimator.getFrameDelay()); } } static void postInvalidateOnAnimation(@NonNull View view) { if (Build.VERSION.SDK_INT >= 16) { view.postInvalidateOnAnimation(); } else { view.postInvalidate(); } } }Z

Slide 215

Slide 215 text

class ViewCompat { static int getPaddingStart(@NonNull View view) { if (Build.VERSION.SDK_INT >= 17) { return view.getPaddingStart(); } return view.getPaddingLeft(); } static int getPaddingEnd(@NonNull View view) { if (Build.VERSION.SDK_INT >= 17) { return view.getPaddingEnd(); } return view.getPaddingRight(); } }Z

Slide 216

Slide 216 text

class ViewCompat { public static boolean isInLayout(@NonNull View view) { if (Build.VERSION.SDK_INT >= 18) { return view.isInLayout(); } return false; } public static boolean isLaidOut(@NonNull View view) { if (Build.VERSION.SDK_INT >= 19) { return view.isLaidOut(); } return view.getWidth() > 0 && view.getHeight() > 0; } }Z

Slide 217

Slide 217 text

class ViewCompat { static void setElevation(@NonNull View view, float elevation) { if (Build.VERSION.SDK_INT >= 21) { view.setElevation(elevation); } } static float getElevation(@NonNull View view) { if (Build.VERSION.SDK_INT >= 21) { return view.getElevation(); } return 0f; } }Z

Slide 218

Slide 218 text

class ViewCompat { static int getMinimumWidth(@NonNull View view) { if (Build.VERSION.SDK_INT >= 16) { return view.getMinimumWidth(); } if (!sMinWidthFieldFetched) { try { sMinWidthField = View.class.getDeclaredField("mMinWidth"); sMinWidthField.setAccessible(true); } catch (NoSuchFieldException e) {} sMinWidthFieldFetched = true; } if (sMinWidthField != null) { try { return (int) sMinWidthField.get(view); } catch (Exception e) {} } return 0; } }Z

Slide 219

Slide 219 text

class ViewCompat { static int getMinimumWidth(@NonNull View view) { if (Build.VERSION.SDK_INT >= 16) { return view.getMinimumWidth(); } if (!sMinWidthFieldFetched) { try { sMinWidthField = View.class.getDeclaredField("mMinWidth"); sMinWidthField.setAccessible(true); } catch (NoSuchFieldException e) {} sMinWidthFieldFetched = true; } if (sMinWidthField != null) { try { return (int) sMinWidthField.get(view); } catch (Exception e) {} } return 0; } }Z

Slide 220

Slide 220 text

class DrawableCompat { static Drawable wrap(@NonNull Drawable drawable) { if (Build.VERSION.SDK_INT >= 23) { return drawable; } if (Build.VERSION.SDK_INT >= 21) { if (!(drawable instanceof TintAwareDrawable)) { return new WrappedDrawableApi21(drawable); } return drawable; } if (!(drawable instanceof TintAwareDrawable)) { return new WrappedDrawableApi14(drawable); } return drawable; } }Z

Slide 221

Slide 221 text

class DrawableCompat { static Drawable wrap(@NonNull Drawable drawable) { if (Build.VERSION.SDK_INT >= 23) { return drawable; } if (Build.VERSION.SDK_INT >= 21) { if (!(drawable instanceof TintAwareDrawable)) { return new WrappedDrawableApi21(drawable); } return drawable; } if (!(drawable instanceof TintAwareDrawable)) { return new WrappedDrawableApi14(drawable); } return drawable; } }Z

Slide 222

Slide 222 text

$ grep -r 'SDK_INT' src/main | egrep '( < | <= | > | >= | ==)' | cut -d':' -f1 | cut -d'/' -f4- | sort | uniq -c | sort -r 124 androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java 103 androidx/core/view/ViewCompat.java 65 androidx/core/app/NotificationCompat.java 30 androidx/core/widget/TextViewCompat.java 25 androidx/core/text/PrecomputedTextCompat.java 23 androidx/core/content/ContextCompat.java 23 androidx/core/app/NotificationCompatBuilder.java 20 androidx/core/view/WindowInsetsCompat.java 20 androidx/core/graphics/drawable/DrawableCompat.java 16 androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java 13 androidx/core/view/MenuItemCompat.java 12 androidx/core/app/ActivityCompat.java 11 androidx/core/view/ViewPropertyAnimatorCompat.java 11 androidx/core/os/BuildCompat.java 11 androidx/core/app/ActivityOptionsCompat.java 10 androidx/core/graphics/drawable/IconCompat.java 9 androidx/core/app/RemoteInput.java 8 androidx/core/view/ViewParentCompat.java 8 androidx/core/view/MarginLayoutParamsCompat.java 7 androidx/core/widget/PopupWindowCompat.java 6 androidx/core/widget/ImageViewCompat.java 6 androidx/core/view/accessibility/AccessibilityEventCompat.java 6 androidx/core/view/ViewConfigurationCompat.java 6 androidx/core/view/DisplayCutoutCompat.java 5 androidx/core/widget/CompoundButtonCompat.java 5 androidx/core/view/accessibility/AccessibilityRecordCompat.java 5 androidx/core/view/ViewGroupCompat.java 5 androidx/core/os/HandlerCompat.java 5 androidx/core/content/res/ResourcesCompat.java 5 androidx/core/app/NotificationManagerCompat.java

Slide 223

Slide 223 text

$ cat SdkIntElevation.java

Slide 224

Slide 224 text

$ cat SdkIntElevation.java import static android.os.Build.VERSION.SDK_INT; import android.view.View; class SdkIntElevation { public static void main(String... args) { View view = new View(null); setElevation(view, 8f); System.out.println(getElevation(view)); }A public static void setElevation(View view, float elevation) { if (SDK_INT >= 21) view.setElevation(elevation); }X public static float getElevation(View view) { return SDK_INT >= 21 ? view.getElevation() : 0f; }Y }Z

Slide 225

Slide 225 text

$ cat SdkIntElevation.java import static android.os.Build.VERSION.SDK_INT; import android.view.View; class SdkIntElevation { public static void main(String... args) { View view = new View(null); setElevation(view, 8f); System.out.println(getElevation(view)); }A public static void setElevation(View view, float elevation) { if (SDK_INT >= 21) view.setElevation(elevation); }X public static float getElevation(View view) { return SDK_INT >= 21 ? view.getElevation() : 0f; }Y }Z
 
 $ javac -bootclasspath $ANDROID_HOME/platforms/android-28/android.jar *.java

Slide 226

Slide 226 text

View view = new View(null); setElevation(view, 8f); System.out.println(getElevation(view)); }A public static void setElevation(View view, float elevation) { if (SDK_INT >= 21) view.setElevation(elevation); }X public static float getElevation(View view) { return SDK_INT >= 21 ? view.getElevation() : 0f; }Y }Z
 
 $ javac -bootclasspath $ANDROID_HOME/platforms/android-28/android.jar *.java
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class

Slide 227

Slide 227 text

System.out.println(getElevation(view)); }A public static void setElevation(View view, float elevation) { if (SDK_INT >= 21) view.setElevation(elevation); }X public static float getElevation(View view) { return SDK_INT >= 21 ? view.getElevation() : 0f; }Y }Z
 
 $ javac -bootclasspath $ANDROID_HOME/platforms/android-28/android.jar *.java
 
 $ java -jar $R8_HOME/build/libs/d8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 228

Slide 228 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [00020c] SdkIntElevation.main:([Ljava/lang/String;)V
 0000: new-instance v1, Landroid/view/View;
 0002: const/4 v0, #int 0
 0003: invoke-direct {v1, v0}, Landroid/view/View;.:(Landroid/content/Context;)V
 0006: const/high16 v0, #int 1090519040
 0008: invoke-static {v1, v0}, LSdkIntElevation;.setElevation:(Landroid/view/View;F)V
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-static {v1}, LSdkIntElevation;.getElevation:(Landroid/view/View;)F
 0010: move-result v1
 0011: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(F)V
 0014: return-void
 
 [0001c8] SdkIntElevation.getElevation:(Landroid/view/View;)F
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 000b
 0006: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F
 0009: move-result v2
 000a: goto 000c
 000b: const/4 v2, #int 0


Slide 229

Slide 229 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [00020c] SdkIntElevation.main:([Ljava/lang/String;)V
 0000: new-instance v1, Landroid/view/View;
 0002: const/4 v0, #int 0
 0003: invoke-direct {v1, v0}, Landroid/view/View;.:(Landroid/content/Context;)V
 0006: const/high16 v0, #int 1090519040
 0008: invoke-static {v1, v0}, LSdkIntElevation;.setElevation:(Landroid/view/View;F)V
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-static {v1}, LSdkIntElevation;.getElevation:(Landroid/view/View;)F
 0010: move-result v1
 0011: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(F)V
 0014: return-void
 
 [0001c8] SdkIntElevation.getElevation:(Landroid/view/View;)F
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 000b
 0006: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F
 0009: move-result v2
 000a: goto 000c
 000b: const/4 v2, #int 0


Slide 230

Slide 230 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [00020c] SdkIntElevation.main:([Ljava/lang/String;)V
 0000: new-instance v1, Landroid/view/View;
 0002: const/4 v0, #int 0
 0003: invoke-direct {v1, v0}, Landroid/view/View;.:(Landroid/content/Context;)V
 0006: const/high16 v0, #int 1090519040
 0008: invoke-static {v1, v0}, LSdkIntElevation;.setElevation:(Landroid/view/View;F)V
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-static {v1}, LSdkIntElevation;.getElevation:(Landroid/view/View;)F
 0010: move-result v1
 0011: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(F)V
 0014: return-void
 
 [0001c8] SdkIntElevation.getElevation:(Landroid/view/View;)F
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 000b
 0006: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F
 0009: move-result v2
 000a: goto 000c
 000b: const/4 v2, #int 0


Slide 231

Slide 231 text

*.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [00020c] SdkIntElevation.main:([Ljava/lang/String;)V
 0000: new-instance v1, Landroid/view/View;
 0002: const/4 v0, #int 0
 0003: invoke-direct {v1, v0}, Landroid/view/View;.:(Landroid/content/Context;)V
 0006: const/high16 v0, #int 1090519040
 0008: invoke-static {v1, v0}, LSdkIntElevation;.setElevation:(Landroid/view/View;F)V
 000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-static {v1}, LSdkIntElevation;.getElevation:(Landroid/view/View;)F
 0010: move-result v1
 0011: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(F)V
 0014: return-void
 
 [0001c8] SdkIntElevation.getElevation:(Landroid/view/View;)F
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 000b
 0006: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F
 0009: move-result v2
 000a: goto 000c
 000b: const/4 v2, #int 0


Slide 232

Slide 232 text

000b: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
 000d: invoke-static {v1}, LSdkIntElevation;.getElevation:(Landroid/view/View;)F
 0010: move-result v1
 0011: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(F)V
 0014: return-void
 
 [0001c8] SdkIntElevation.getElevation:(Landroid/view/View;)F
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 000b
 0006: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F
 0009: move-result v2
 000a: goto 000c
 000b: const/4 v2, #int 0
 000c: return v2
 
 [000248] SdkIntElevation.setElevation:(Landroid/view/View;F)V
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 0009
 0006: invoke-virtual {v2, v3}, Landroid/view/View;.setElevation:(F)V
 0009: return-void

Slide 233

Slide 233 text

0010: move-result v1
 0011: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(F)V
 0014: return-void
 
 [0001c8] SdkIntElevation.getElevation:(Landroid/view/View;)F
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 000b
 0006: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F
 0009: move-result v2
 000a: goto 000c
 000b: const/4 v2, #int 0
 000c: return v2
 
 [000248] SdkIntElevation.setElevation:(Landroid/view/View;F)V
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 0009
 0006: invoke-virtual {v2, v3}, Landroid/view/View;.setElevation:(F)V
 0009: return-void
 
 $ cat rules.txt

Slide 234

Slide 234 text

0006: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F
 0009: move-result v2
 000a: goto 000c
 000b: const/4 v2, #int 0
 000c: return v2
 
 [000248] SdkIntElevation.setElevation:(Landroid/view/View;F)V
 0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 0009
 0006: invoke-virtual {v2, v3}, Landroid/view/View;.setElevation:(F)V
 0009: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A

Slide 235

Slide 235 text

0000: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I
 0002: const/16 v1, #int 21
 0004: if-lt v0, v1, 0009
 0006: invoke-virtual {v2, v3}, Landroid/view/View;.setElevation:(F)V
 0009: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class

Slide 236

Slide 236 text

0004: if-lt v0, v1, 0009
 0006: invoke-virtual {v2, v3}, Landroid/view/View;.setElevation:(F)V
 0009: return-void
 
 $ cat rules.txt -keepclasseswithmembers class * { public static void main(...);
 }B 
 -assumevalues class android.os.Build$VERSION { int SDK_INT return 21..2147483647; }A
 
 $ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex

Slide 237

Slide 237 text

$ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [00017c] SdkIntElevation.main:([Ljava/lang/String;)V 0000: new-instance v2, Landroid/view/View; 0002: const/4 v0, #int 0 0003: invoke-direct {v2, v0}, Landroid/view/View;.:(Landroid/content/Context;)V 0006: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I 0008: const/high16 v0, #int 1090519040 000a: invoke-virtual {v2, v0}, Landroid/view/View;.setElevation:(F)V 000d: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; 000f: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I 0011: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F 0014: move-result v2 0015: invoke-virtual {v0, v2}, Ljava/io/PrintStream;.println:(F)V 0018: return-void

Slide 238

Slide 238 text

$ java -jar $R8_HOME/build/libs/r8.jar \
 --lib $ANDROID_HOME/platforms/android-28/android.jar \
 --release \
 --output . \
 --pg-conf rules.txt \
 *.class
 
 $ $ANDROID_HOME/build-tools/28.0.2/dexdump -d classes.dex [00017c] SdkIntElevation.main:([Ljava/lang/String;)V 0000: new-instance v2, Landroid/view/View; 0002: const/4 v0, #int 0 0003: invoke-direct {v2, v0}, Landroid/view/View;.:(Landroid/content/Context;)V 0006: sget v0, Landroid/os/Build$VERSION;.SDK_INT:I 0008: const/high16 v0, #int 1090519040 000a: invoke-virtual {v2, v0}, Landroid/view/View;.setElevation:(F)V 000d: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; 000f: sget v1, Landroid/os/Build$VERSION;.SDK_INT:I 0011: invoke-virtual {v2}, Landroid/view/View;.getElevation:()F 0014: move-result v2 0015: invoke-virtual {v0, v2}, Ljava/io/PrintStream;.println:(F)V 0018: return-void

Slide 239

Slide 239 text

$ grep -r 'SDK_INT' src/main | egrep '( < | <= | > | >= | ==)' | cut -d':' -f1 | cut -d'/' -f4- | sort | uniq -c | sort -r 124 androidx/core/view/accessibility/AccessibilityNodeInfoCompat.java 103 androidx/core/view/ViewCompat.java 65 androidx/core/app/NotificationCompat.java 30 androidx/core/widget/TextViewCompat.java 25 androidx/core/text/PrecomputedTextCompat.java 23 androidx/core/content/ContextCompat.java 23 androidx/core/app/NotificationCompatBuilder.java 20 androidx/core/view/WindowInsetsCompat.java 20 androidx/core/graphics/drawable/DrawableCompat.java 16 androidx/core/view/accessibility/AccessibilityWindowInfoCompat.java 13 androidx/core/view/MenuItemCompat.java 12 androidx/core/app/ActivityCompat.java 11 androidx/core/view/ViewPropertyAnimatorCompat.java 11 androidx/core/os/BuildCompat.java 11 androidx/core/app/ActivityOptionsCompat.java 10 androidx/core/graphics/drawable/IconCompat.java 9 androidx/core/app/RemoteInput.java 8 androidx/core/view/ViewParentCompat.java 8 androidx/core/view/MarginLayoutParamsCompat.java 7 androidx/core/widget/PopupWindowCompat.java 6 androidx/core/widget/ImageViewCompat.java 6 androidx/core/view/accessibility/AccessibilityEventCompat.java 6 androidx/core/view/ViewConfigurationCompat.java 6 androidx/core/view/DisplayCutoutCompat.java 5 androidx/core/widget/CompoundButtonCompat.java 5 androidx/core/view/accessibility/AccessibilityRecordCompat.java 5 androidx/core/view/ViewGroupCompat.java 5 androidx/core/os/HandlerCompat.java 5 androidx/core/content/res/ResourcesCompat.java 5 androidx/core/app/NotificationManagerCompat.java

Slide 240

Slide 240 text

$ cat gradle.properties

Slide 241

Slide 241 text

$ cat gradle.properties
 
 # Use R8 instead of ProGuard for code shrinking. android.enableR8=true

Slide 242

Slide 242 text

No content

Slide 243

Slide 243 text

No content

Slide 244

Slide 244 text

No content

Slide 245

Slide 245 text

No content

Slide 246

Slide 246 text

No content

Slide 247

Slide 247 text

No content

Slide 248

Slide 248 text

No content

Slide 249

Slide 249 text

No content

Slide 250

Slide 250 text

No content

Slide 251

Slide 251 text

No content

Slide 252

Slide 252 text

No content

Slide 253

Slide 253 text

No content

Slide 254

Slide 254 text

https://jakes.link/java-bytecode

Slide 255

Slide 255 text

DIGGING INTO D8 AND R8 @JakeWharton