Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Digging Into D8 and R8 (Droidcon NYC 2018)

Digging Into D8 and R8 (Droidcon NYC 2018)

D8 has replaced DX as the default dexer, the tool which converts Java bytecode to Dalvik bytecode. R8 is coming as the default shrinker, the tool which removes and optimizes code. While you may have heard about one or both of these tools before, not a lot of information exists on the advantages they bring. This talk will cover those advantages both in the scope of your entire application but also with very localized examples in a single class or method. We'll also look at some tricks that D8 and R8 can do which their predecessors could not. Finally, we'll cover how to enable both tools in your build and recommendations to ensure you're getting the most out of each.

Video: https://youtu.be/99H7COwhIpI

Jake Wharton

August 27, 2018
Tweet

More Decks by Jake Wharton

Other Decks in Programming

Transcript

  1. DIGGING
    INTO
    D8
    AND
    R8
    @JakeWharton

    View full-size slide

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

    View full-size slide

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


    $ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

    View full-size slide

  4. $ 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.

    View full-size slide

  5. $ 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

    View full-size slide

  6. $ 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

    View full-size slide

  7. $ 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.

    View full-size slide


  8. $ 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

    View full-size slide

  9. 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

    View full-size slide


  10. $ 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

    View full-size slide

  11. 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`

    View full-size slide

  12. dx
    compilers
    sources
    libraries
    transforms

    View full-size slide

  13. $ cat Java8.java

    View full-size slide

  14. $ 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!");
    }
    }

    View full-size slide

  15. $ 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

    View full-size slide

  16. $ 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

    View full-size slide

  17. $ 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

    View full-size slide

  18. 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

    View full-size slide

  19. 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

    View full-size slide

  20. dx
    compilers
    sources
    libraries
    transforms

    View full-size slide

  21. Desugar
    dx
    compilers
    sources
    libraries
    transforms

    View full-size slide

  22. Desugar
    dx
    compilers
    sources
    libraries
    transforms

    View full-size slide

  23. Desugar
    D8
    compilers
    sources
    libraries
    transforms

    View full-size slide

  24. D8
    compilers
    sources
    libraries
    transforms
    Desugar

    View full-size slide

  25. Desugar
    D8
    compilers
    sources
    libraries
    transforms

    View full-size slide

  26. 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

    View full-size slide

  27. }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

    View full-size slide


  28. $ 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

    View full-size slide

  29. 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

    View full-size slide

  30. $ $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 ()

    View full-size slide

  31. 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

    View full-size slide

  32. $ $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

    View full-size slide

  33. $ $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

    View full-size slide

  34. $ $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

    View full-size slide

  35. $ $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

    View full-size slide

  36. $ $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

    View full-size slide

  37. $ $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

    View full-size slide

  38. $ $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

    View full-size slide

  39. $ $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

    View full-size slide

  40. $ $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

    View full-size slide

  41. $ $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

    View full-size slide

  42. $ $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

    View full-size slide

  43. 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

    View full-size slide

  44. 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

    View full-size slide

  45. 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

    View full-size slide

  46. 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

    View full-size slide

  47. 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

    View full-size slide

  48. 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

    View full-size slide

  49. 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

    View full-size slide

  50. 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

    View full-size slide

  51. 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

    View full-size slide

  52. 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

    View full-size slide

  53. 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

    View full-size slide

  54. 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

    View full-size slide

  55. 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

    View full-size slide

  56. 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

    View full-size slide

  57. 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

    View full-size slide

  58. 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

    View full-size slide

  59. 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

    View full-size slide

  60. 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

    View full-size slide

  61. 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

    View full-size slide

  62. 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

    View full-size slide

  63. 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

    View full-size slide

  64. 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

    View full-size slide

  65. 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

    View full-size slide

  66. 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

    View full-size slide

  67. 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

    View full-size slide

  68. 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

    View full-size slide

  69. 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

    View full-size slide

  70. 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

    View full-size slide

  71. $ cat Not.java

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  74. $ 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

    View full-size slide

  75. $ 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

    View full-size slide

  76. 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

    View full-size slide

  77. 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

    View full-size slide

  78. 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

    View full-size slide

  79. 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

    View full-size slide

  80. 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
    =

    View full-size slide

  81. 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

    View full-size slide

  82. 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

    View full-size slide

  83. 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

    View full-size slide

  84. 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

    View full-size slide

  85. 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

    View full-size slide

  86. 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

    View full-size slide

  87. 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

    View full-size slide

  88. 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

    View full-size slide

  89. 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

    View full-size slide

  90. 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

    View full-size slide

  91. $ 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

    View full-size slide

  92. $ 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

    View full-size slide

  93. $ 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

    View full-size slide

  94. --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

    View full-size slide

  95. [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

    View full-size slide

  96. [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

    View full-size slide

  97. [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

    View full-size slide

  98. [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

    View full-size slide

  99. [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

    View full-size slide

  100. [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

    View full-size slide

  101. [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

    View full-size slide

  102. D8
    compilers
    sources
    libraries
    transforms

    View full-size slide

  103. ProGuard
    D8
    compilers
    sources
    libraries
    transforms

    View full-size slide

  104. D8
    compilers
    sources
    libraries
    transforms
    ProGuard

    View full-size slide

  105. ProGuard
    compilers
    sources
    libraries
    transforms R8

    View full-size slide

  106. $ cat Greeter.kt

    View full-size slide

  107. $ 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)
    }
    }

    View full-size slide

  108. $ 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)
    }
    }

    View full-size slide

  109. $ 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)
    }
    }

    View full-size slide

  110. $ 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)
    }
    }

    View full-size slide

  111. $ 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)
    }
    }

    View full-size slide

  112. $ 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

    View full-size slide

  113. 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

    View full-size slide

  114. 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

    View full-size slide

  115. --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

    View full-size slide

  116. --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

    View full-size slide

  117. --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

    View full-size slide

  118. --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

    View full-size slide

  119. --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

    View full-size slide

  120. 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

    View full-size slide

  121. 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

    View full-size slide

  122. 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

    View full-size slide

  123. 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

    View full-size slide

  124. 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

    View full-size slide

  125. 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

    View full-size slide

  126. *.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

    View full-size slide

  127. *.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

    View full-size slide

  128. *.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

    View full-size slide


  129. $ $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

    View full-size slide


  130. $ $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

    View full-size slide


  131. $ $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

    View full-size slide

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

    View full-size slide

  133. 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

    View full-size slide

  134. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  137. 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

    View full-size slide

  138. 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

    View full-size slide

  139. 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

    View full-size slide

  140. --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

    View full-size slide

  141. --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

    View full-size slide

  142. --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

    View full-size slide

  143. --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

    View full-size slide

  144. --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

    View full-size slide

  145. 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

    View full-size slide

  146. 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

    View full-size slide


  147. $ $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

    View full-size slide

  148. $ $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

    View full-size slide

  149. $ $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

    View full-size slide

  150. $ $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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  153. $ cat Nulls.kt

    View full-size slide

  154. $ 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"))
    }

    View full-size slide

  155. $ 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"))
    }

    View full-size slide

  156. $ 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"))
    }

    View full-size slide

  157. $ 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"))
    }

    View full-size slide

  158. $ 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"))
    }

    View full-size slide

  159. $ 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

    View full-size slide

  160. $ 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

    View full-size slide

  161. 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

    View full-size slide

  162. *.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


    View full-size slide

  163. *.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


    View full-size slide

  164. *.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


    View full-size slide

  165. *.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


    View full-size slide

  166. *.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


    View full-size slide

  167. 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

    View full-size slide

  168. 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

    View full-size slide

  169. 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

    View full-size slide

  170. 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

    View full-size slide

  171. 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

    View full-size slide

  172. 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

    View full-size slide

  173. 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

    View full-size slide

  174. 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

    View full-size slide

  175. 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

    View full-size slide

  176. --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…)

    View full-size slide

  177. --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…)

    View full-size slide

  178. --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…)

    View full-size slide

  179. --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…)

    View full-size slide

  180. --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…)

    View full-size slide

  181. --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…)

    View full-size slide

  182. $ cat SdkIntSimple.java

    View full-size slide

  183. $ 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");
    }
    }
    }

    View full-size slide

  184. $ 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

    View full-size slide

  185. 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

    View full-size slide

  186. 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

    View full-size slide

  187. *.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

    View full-size slide

  188. *.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

    View full-size slide

  189. *.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

    View full-size slide

  190. *.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

    View full-size slide

  191. *.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

    View full-size slide

  192. *.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

    View full-size slide

  193. *.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

    View full-size slide

  194. $ $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

    View full-size slide

  195. 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

    View full-size slide

  196. 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

    View full-size slide

  197. 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

    View full-size slide

  198. 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

    View full-size slide

  199. 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

    View full-size slide

  200. 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

    View full-size slide

  201. 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

    View full-size slide

  202. 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

    View full-size slide

  203. 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

    View full-size slide

  204. 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;
    }

    View full-size slide

  205. 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

    View full-size slide

  206. 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

    View full-size slide

  207. 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

    View full-size slide

  208. 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

    View full-size slide

  209. 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

    View full-size slide

  210. 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

    View full-size slide

  211. 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

    View full-size slide

  212. 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

    View full-size slide

  213. 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

    View full-size slide

  214. 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

    View full-size slide

  215. 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

    View full-size slide

  216. 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

    View full-size slide

  217. 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

    View full-size slide

  218. 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

    View full-size slide

  219. 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

    View full-size slide

  220. $ 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

    View full-size slide

  221. $ cat SdkIntElevation.java

    View full-size slide

  222. $ 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

    View full-size slide

  223. $ 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

    View full-size slide

  224. 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

    View full-size slide

  225. 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

    View full-size slide

  226. *.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


    View full-size slide

  227. *.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


    View full-size slide

  228. *.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


    View full-size slide

  229. *.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


    View full-size slide

  230. 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

    View full-size slide

  231. 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

    View full-size slide

  232. 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

    View full-size slide

  233. 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

    View full-size slide

  234. 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

    View full-size slide

  235. $ 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

    View full-size slide

  236. $ 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

    View full-size slide

  237. $ 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

    View full-size slide

  238. $ cat gradle.properties

    View full-size slide

  239. $ cat gradle.properties


    # Use R8 instead of ProGuard for code shrinking.
    android.enableR8=true

    View full-size slide

  240. https://jakes.link/java-bytecode

    View full-size slide

  241. DIGGING
    INTO
    D8
    AND
    R8
    @JakeWharton

    View full-size slide