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

Exploring Hidden Java Costs (360|AnDev, July 2016)

Exploring Hidden Java Costs (360|AnDev, July 2016)

As Java 8 features comes to Android, it’s important to remember that every standard library API and language feature comes with an associated cost. Even as devices get faster and have more memory, concerns of code size and performance overhead are still very relevant. This talk will be an exploration into hidden costs associated with some of Java’s features. We’ll focus on optimizations relevant for both library and application developers and on the tools that can be used to measure their impact.

Video: https://www.youtube.com/watch?v=WALV33rWye4

Jake Wharton
PRO

July 29, 2016
Tweet

More Decks by Jake Wharton

Other Decks in Programming

Transcript

  1. Jake Wharton
    Exploring
    Java Hidden
    Costs

    View Slide

  2. 2?
    0? 1?
    How many methods?
    class Example {

    }"

    View Slide

  3. How many methods?
    class Example {

    }"
    2?
    0! 1?

    View Slide

  4. How many methods?
    $ echo "class Example {

    }" > Example.java
    2?
    0! 1?

    View Slide

  5. How many methods?
    $ echo "class Example {

    }" > Example.java
    $ javac Example.java
    2?
    0! 1?

    View Slide

  6. How many methods?
    $ echo "class Example {

    }" > Example.java
    $ javac Example.java
    $ javap Example.class
    2?
    0! 1?

    View Slide

  7. How many methods?
    $ echo "class Example {

    }" > Example.java
    $ javac Example.java
    $ javap Example.class
    class Example {
    Example();
    }
    2?
    0! 1?

    View Slide

  8. $ echo "class Example {

    }" > Example.java
    $ javac Example.java
    $ javap Example.class
    class Example {
    Example();
    }
    How many methods?
    $ echo "class Example {

    }" > Example.java
    $ javac Example.java
    $ javap Example.class
    class Example {
    Example();
    }
    2?
    0! 1?
    How many methods? 0! 1? 2?

    View Slide

  9. $ echo "class Example {

    }" > Example.java
    $ javac Example.java
    $ javap Example.class
    class Example {
    Example();
    }
    How many methods? 2?
    0! 1!

    View Slide

  10. $ dx --dex --output=example.dex Example.class
    How many methods? 2?
    0! 1!

    View Slide

  11. $ dx --dex --output=example.dex Example.class
    $ dexdump -f example.dex
    How many methods? 2?
    0! 1!

    View Slide

  12. $ dx --dex --output=example.dex Example.class
    $ dexdump -f example.dex
    Opened 'example.dex', DEX version '035'
    DEX file header:
    magic : 'dex\n035\0'
    checksum : b4e92dde
    signature : f51f...a6a1
    file_size : 436
    header_size : 112
    link_size : 0
    link_off : 0 (0x000000)
    string_ids_size : 5
    string_ids_off : 112 (0x000070)
    type_ids_size : 3
    type_ids_off : 132 (0x000084)
    proto_ids_size : 1
    proto_ids_off : 144 (0x000090)
    field_ids_size : 0
    field_ids_off : 0 (0x000000)
    method_ids_size : 2
    method_ids_off : 156 (0x00009c)
    class_defs_size : 1
    class_defs_off : 172 (0x0000ac)
    data_size : 232
    data_off : 204 (0x0000cc)
    How many methods? 2?
    0! 1!

    View Slide

  13. $ dx --dex --output=example.dex Example.class
    $ dexdump -f example.dex
    Opened 'example.dex', DEX version '035'
    DEX file header:
    magic : 'dex\n035\0'
    checksum : b4e92dde
    signature : f51f...a6a1
    file_size : 436
    header_size : 112
    link_size : 0
    link_off : 0 (0x000000)
    string_ids_size : 5
    string_ids_off : 112 (0x000070)
    type_ids_size : 3
    type_ids_off : 132 (0x000084)
    proto_ids_size : 1
    proto_ids_off : 144 (0x000090)
    field_ids_size : 0
    field_ids_off : 0 (0x000000)
    method_ids_size : 2
    method_ids_off : 156 (0x00009c)
    class_defs_size : 1
    class_defs_off : 172 (0x0000ac)
    data_size : 232
    data_off : 204 (0x0000cc)
    How many methods?
    $ dx --dex --output=example.dex Example.class
    $ dexdump -f example.dex
    Opened 'example.dex', DEX version '035'
    DEX file header:
    magic : 'dex\n035\0'
    checksum : b4e92dde
    signature : f51f...a6a1
    file_size : 436
    header_size : 112
    link_size : 0
    link_off : 0 (0x000000)
    string_ids_size : 5
    string_ids_off : 112 (0x000070)
    type_ids_size : 3
    type_ids_off : 132 (0x000084)
    proto_ids_size : 1
    proto_ids_off : 144 (0x000090)
    field_ids_size : 0
    field_ids_off : 0 (0x000000)
    method_ids_size : 2
    method_ids_off : 156 (0x00009c)
    class_defs_size : 1
    class_defs_off : 172 (0x0000ac)
    data_size : 232
    data_off : 204 (0x0000cc)
    2?
    0! 1!

    View Slide

  14. $ dex-method-list example.dex
    How many methods? 2?
    0! 1!

    View Slide

  15. $ dex-method-list example.dex
    Example ()
    java.lang.Object ()
    How many methods? 2?
    0! 1!

    View Slide

  16. $ dex-method-list example.dex
    Example ()
    java.lang.Object ()
    $ javap -c Example.class
    How many methods? 2?
    0! 1!

    View Slide

  17. $ dex-method-list example.dex
    Example ()
    java.lang.Object ()
    $ javap -c Example.class
    class Example {
    Example();
    Code:
    0: aload_0
    1: invokespecial #1 //java/lang/Object."":()V
    4: return
    }
    How many methods? 2?
    0! 1!

    View Slide

  18. $ dex-method-list example.dex
    Example ()
    java.lang.Object ()
    $ javap -c Example.class
    class Example {
    Example();
    Code:
    0: aload_0
    1: invokespecial #1 //java/lang/Object."":()V
    4: return
    }
    How many methods? 2?
    0! 1!
    $ dex-method-list example.dex
    Example ()
    java.lang.Object ()
    $ javap -c Example.class
    class Example {
    Example();
    Code:
    0: aload_0
    1: invokespecial #1 //java/lang/Object."":()V
    4: return
    }
    2?
    0! 1!
    How many methods?

    View Slide

  19. $ dex-method-list example.dex
    Example ()
    java.lang.Object ()
    $ javap -c Example.class
    class Example {
    Example();
    Code:
    0: aload_0
    1: invokespecial #1 //java/lang/Object."":()V
    4: return
    }
    How many methods? 2!
    0! 1!

    View Slide

  20. How many methods?
    2
    0
    1
    class Example {

    }"
    0 declared methods
    0 in the source file

    View Slide

  21. How many methods?
    2
    1
    class Example {

    }"
    0 declared methods
    0 in the source file
    0 and only humans care

    View Slide

  22. How many methods?
    2
    class Example {

    }"
    0 declared methods
    1
    1 compiled method
    0 in the class file

    View Slide

  23. How many methods?
    2
    class Example {

    }"
    0 declared methods
    1 compiled method
    2 referenced methods
    0 in the dex file

    View Slide

  24. How many methods?
    class Example {

    }3
    0 declared methods
    1 compiled method
    2 referenced methods
    0 in the dex file
    0 for the true "method count"

    View Slide

  25. // Outer.java
    public class OuterA{1
    private class Example {2
    }3

    }4

    View Slide

  26. // ItemsView.java
    public class ItemsViewA{1
    private class ItemsAdapter {2
    }3

    }4
    Outer
    Outer
    Example

    View Slide

  27. // ItemsView.java
    public class ItemsView {
    private class ItemsAdapter {
    }

    }"
    $ javac ItemsView.java

    View Slide

  28. // ItemsView.java
    public class ItemsView {
    private class ItemsAdapter {
    }

    }"
    $ javac ItemsView.java
    $ ls
    ItemsView.class
    ItemsView.java
    ItemsView$ItemsAdapter.class

    View Slide

  29. // ItemsView.java
    public class ItemsView {
    private class ItemsAdapter {
    }

    }"

    $ javap ItemsView
    public class ItemsView {
    public ItemsView();
    }

    View Slide

  30. // ItemsView.java
    public class ItemsView {
    private class ItemsAdapter {
    }G

    }"

    $ javap 'ItemsView$ItemsAdapter'
    class ItemsView$ItemsAdapter {
    ItemsView$ItemsAdapter();
    }

    // ItemsAdapter.java

    View Slide

  31. // ItemsView.java
    public class ItemsView {
    private class ItemsAdapter {
    }G

    }"

    // ItemsAdapter.java

    View Slide

  32. // ItemsView.java
    public class ItemsView {

    }"
    // ItemsAdapter.java
    class ItemsAdapter {
    }G

    View Slide

  33. // ItemsView.java
    public class ItemsView {

    }"
    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {
    }G

    View Slide

  34. // ItemsView.java
    public class ItemsView {
    private class ItemsAdapter {
    }G

    }"

    // ItemsView$ItemsAdapter.java
    ItemsView$

    View Slide

  35. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L


    private class ItemsAdapter {

    }G

    }"

    View Slide

  36. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L


    private class ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G

    }"





    // ItemsView$ItemsAdapter.java
    ItemsView$

    View Slide

  37. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L


    private class ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G

    }"

    View Slide

  38. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L

    }"

    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G





    private

    View Slide

  39. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L

    }"

    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G





    private
    // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }

    }"

    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }

    }

    View Slide

  40. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L


    private class ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G

    }"

    View Slide

  41. $ javac -bootclasspath android-sdk/platforms/android-24/android.jar \
    ItemsView.java
    $ javap -c 'ItemsView$ItemsAdapter'

    View Slide

  42. $ javac -bootclasspath android-sdk/platforms/android-24/android.jar \
    ItemsView.java
    $ javap -c 'ItemsView$ItemsAdapter'
    class ItemsView$ItemAdapter {
    void bindItem(android.widget.TextView, java.lang.String);
    Code:
    0: aload_1
    1: aload_2
    2: invokestatic #3 // Method ItemsView.access$000:…
    5: invokevirtual #4 // Method TextView.setText:…
    8: return
    }

    View Slide

  43. $ javac -bootclasspath android-sdk/platforms/android-24/android.jar \
    ItemsView.java
    $ javap -c 'ItemsView$ItemsAdapter'
    class ItemsView$ItemAdapter {
    void bindItem(android.widget.TextView, java.lang.String);
    Code:
    0: aload_1
    1: aload_2
    2: invokestatic #3 // Method ItemsView.access$000:…
    5: invokevirtual #4 // Method TextView.setText:…
    8: return
    }

    View Slide

  44. $ javap -p ItemsView

    View Slide

  45. $ javap -p ItemsView123
    class ItemsView {
    ItemsView();
    private static java.lang.String displayText(…);
    static java.lang.String access$000(…);
    }
    -c

    View Slide

  46. $ javap -p -c ItemsView123

    View Slide

  47. $ javap -p -c ItemsView123
    class ItemsView {
    ItemsView();
    Code:
    private static java.lang.String displayText(…);
    Code:
    static java.lang.String access$000(…);
    Code:
    0: aload_0
    1: invokestatic #1 // Method displayText:…
    4: areturn
    }

    View Slide

  48. $ javap -p -c ItemsView
    class ItemsView {
    ItemsView();
    Code:
    private static java.lang.String displayText(…);
    Code:
    static java.lang.String access$000(…);
    Code:
    0: aload_0
    1: invokestatic #1 // Method displayText:…
    4: areturn
    }

    View Slide

  49. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }B

    }A

    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }b

    }a

    View Slide

  50. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }B
    static String access$000(String item) {

    return displayText(item);

    }C

    }A

    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }b

    }a
    // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }B
    static String access$000(String item) {

    return displayText(item);

    }C

    }A

    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }b

    }a

    View Slide

  51. // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }B
    static String access$000(String item) {

    return displayText(item);

    }C

    }A

    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.access$000(item));

    }b

    }a
    // ItemsView.java
    public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }B
    static String access$000(String item) {

    return displayText(item);

    }C

    }A

    // ItemsView$ItemsAdapter.java
    class ItemsView$ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.access$000(item));

    }b

    }a








    displayText

    View Slide

  52. $ dx --dex --output=example.dex *.class
    $ dex-method-list example.dex

    View Slide

  53. $ dx --dex --output=example.dex *.class
    $ dex-method-list example.dex
    ItemsView ()
    ItemsView access$000(String) → String
    ItemsView displayText(String) → String
    ItemsView$ItemsAdapter (ItemsView)
    ItemsView$ItemsAdapter bindItem(TextView, String)
    android.widget.TextView setText(CharSequence)
    java.lang.Object ()

    View Slide

  54. $ dx --dex --output=example.dex *.class
    $ dex-method-list example.dex
    ItemsView ()
    ItemsView access$000(String) → String
    ItemsView displayText(String) → String
    ItemsView$ItemsAdapter (ItemsView)
    ItemsView$ItemsAdapter bindItem(TextView, String)
    android.widget.TextView setText(CharSequence)
    java.lang.Object ()

    View Slide

  55. $ java -jar android-sdk/build-tools/24.0.1/jack.jar \
    -cp android-sdk/platforms/android-24/android.jar \
    --output-dex . \
    ItemsView.java
    $ dex-method-list classes.dex

    View Slide

  56. $ java -jar android-sdk/build-tools/24.0.1/jack.jar \
    -cp android-sdk/platforms/android-24/android.jar \
    --output-dex . \
    ItemsView.java
    $ dex-method-list classes.dex
    ItemsView -wrap0(String) → String
    ItemsView ()
    ItemsView displayText(String) → String
    ItemsView$ItemsAdapter (ItemsView)
    ItemsView$ItemsAdapter bindItem(TextView, String)
    android.widget.TextView setText(CharSequence)
    java.lang.Object ()

    View Slide

  57. $ java -jar android-sdk/build-tools/24.0.1/jack.jar \
    -cp android-sdk/platforms/android-24/android.jar \
    --output-dex . \
    ItemsView.java
    $ dex-method-list classes.dex
    ItemsView -wrap0(String) → String
    ItemsView ()
    ItemsView displayText(String) → String
    ItemsView$ItemsAdapter (ItemsView)
    ItemsView$ItemsAdapter bindItem(TextView, String)
    android.widget.TextView setText(CharSequence)
    java.lang.Object ()

    View Slide

  58. $ echo "-dontobfuscate
    -keep class ItemsView$ItemsAdapter { void bindItem(...); }
    " > rules.txt
    $ java -jar proguard-base-5.2.1.jar \
    -include rules.txt \
    -injars . \
    -outjars example-proguard.jar \
    -libraryjars android-sdk/platforms/android-24/android.jar
    $ dex-method-list example-proguard.jar
    $ dex-method-list example-proguard.jar

    View Slide

  59. $ echo "-dontobfuscate
    -keep class ItemsView$ItemsAdapter { void bindItem(...); }
    " > rules.txt
    $ java -jar proguard-base-5.2.1.jar \
    -include rules.txt \
    -injars . \
    -outjars example-proguard.jar \
    -libraryjars android-sdk/platforms/android-24/android.jar
    $ dex-method-list example-proguard.jar
    ItemsView access$000(String) → String
    ItemsView$ItemsAdapter bindItem(TextView, String)
    android.widget.TextView setText(CharSequence)

    View Slide

  60. $ dex-method-list example-proguard.jar
    ItemsView access$000(String) → String
    ItemsView$ItemsAdapter bindItem(TextView, String)
    android.widget.TextView setText(CharSequence)

    View Slide

  61. $ dex-method-list example-proguard.jar
    ItemsView ()
    ItemsView access$000(String) → String
    ItemsView$ItemsAdapter (ItemsView)
    ItemsView$ItemsAdapter bindItem(TextView, String)
    android.widget.TextView setText(CharSequence)
    java.lang.Object ()

    View Slide

  62. $ dex-method-list example-proguard.jar
    ItemsView ()
    ItemsView access$000(String) → String
    ItemsView$ItemsAdapter (ItemsView)
    ItemsView$ItemsAdapter bindItem(TextView, String)
    android.widget.TextView setText(CharSequence)
    java.lang.Object ()

    View Slide

  63. $ unzip example-proguard.jar
    $ unzip example-proguard.jar
    $ javap -c ItemsView

    View Slide

  64. $ unzip example-proguard.jar
    $ javap -c ItemsView
    public final class ItemsView {
    static java.lang.String access$000(java.lang.String);
    Code:
    0: ldc #1 // String ""
    2: areturn
    }

    View Slide

  65. class MyActivity extends Activity {

    @Override protected void onCreate(Bundle state) {

    super.onCreate(state);

    setContentView(R.layout.whatever);

    findViewById(R.id.button).setOnClickListener(
    new OnClickListener() {

    @Override public void onClick(View view) {

    // Hello!

    }

    });

    }

    }

    View Slide

  66. class MyActivity extends Activity {

    @Override protected void onCreate(Bundle state) {

    super.onCreate(state);

    setContentView(R.layout.whatever);

    findViewById(R.id.button).setOnClickListener(
    new OnClickListener() {

    @Override public void onClick(View view) {

    // Hello!

    }C

    });

    }B

    }A

    View Slide

  67. class MyActivity extends Activity {

    @Override protected void onCreate(Bundle state) {

    super.onCreate(state);

    setContentView(R.layout.whatever);

    findViewById(R.id.button).setOnClickListener(
    new OnClickListener() {

    @Override public void onClick(View view) {

    doSomething();
    }C

    });

    }B
    private void doSomething() {

    // ...

    }D

    }A





    // Hello!

    View Slide

  68. class MyActivity extends Activity {

    private int count;

    @Override protected void onCreate(Bundle state) {

    super.onCreate(state);

    setContentView(R.layout.whatever);

    findViewById(R.id.button).setOnClickListener(
    new OnClickListener() {

    @Override public void onClick(View view) {

    count = 0;

    ++count;

    --count;

    count++;

    count--;

    Log.d("Count", "= " + count);
    }C

    });

    }B

    }A






    doSomething();


    private void doSomething() {

    // ...

    }D


    View Slide

  69. class MyActivity extends Activity {

    private int count;

    @Override protected void onCreate(Bundle state) {

    super.onCreate(state);

    setContentView(R.layout.whatever);

    findViewById(R.id.button).setOnClickListener(
    new OnClickListener() {

    @Override public void onClick(View view) {

    count = 0;

    ++count;

    --count;

    count++;

    count--;

    Log.d("Count", "= " + count);
    }C

    });

    }B

    }A

    View Slide

  70. class MyActivity extends Activity {

    private int count;

    @Override protected void onCreate(Bundle state) {

    super.onCreate(state);

    setContentView(R.layout.whatever);

    findViewById(R.id.button).setOnClickListener(
    new OnClickListener() {

    @Override public void onClick(View view) {

    count = 0;

    ++count;

    --count;

    count++;

    count--;

    Log.d("Count", "= " + count);
    }C

    });

    }B

    }A

    View Slide

  71. $ javac -bootclasspath android-sdk/platforms/android-24/android.jar \
    MyActivity.java
    $ javap MyActivity

    View Slide

  72. $ javac -bootclasspath android-sdk/platforms/android-24/android.jar \
    MyActivity.java
    $ javap MyActivity
    class MyActivity extends android.app.Activity {
    MyActivity();
    protected void onCreate(android.os.Bundle);
    static int access$002(MyActivity, int);
    static int access$004(MyActivity);
    static int access$006(MyActivity);
    static int access$008(MyActivity);
    static int access$010(MyActivity);
    static int access$000(MyActivity);
    }

    View Slide

  73. $ javac -bootclasspath android-sdk/platforms/android-24/android.jar \
    MyActivity.java
    $ javap MyActivity
    class MyActivity extends android.app.Activity {
    MyActivity();
    protected void onCreate(android.os.Bundle);
    static int access$002(MyActivity, int);
    static int access$004(MyActivity);
    static int access$006(MyActivity);
    static int access$008(MyActivity);
    static int access$010(MyActivity);
    static int access$000(MyActivity);
    }
    // count = 0 write
    // ++count preinc
    // --count predec
    // count++ postinc
    // count-- postdec
    // count read

    View Slide

  74. $ adb shell mkdir /mnt/sdcard/apks
    $ adb shell cmd package list packages -3 -f \
    | cut -c 9- \
    | sed 's|=| /mnt/sdcard/apks/|' \
    | xargs -t -L1 adb shell cp
    $ adb pull /mnt/sdkcard/apks

    View Slide

  75. accessors.sh
    #!/bin/bash

    set -e


    METHODS=$(dex-method-list $1 | \grep 'access\$')

    ACCESSORS=$(echo "$METHODS" | wc -l | xargs)

    METHOD_AND_READ=$(echo "$METHODS" | egrep 'access\$\d+00\(' | wc -l | xargs)

    WRITE=$(echo "$METHODS" | egrep 'access\$\d+02\(' | wc -l | xargs)

    PREINC=$(echo "$METHODS" | egrep 'access\$\d+04\(' | wc -l | xargs)

    PREDEC=$(echo "$METHODS" | egrep 'access\$\d+06\(' | wc -l | xargs)

    POSTINC=$(echo "$METHODS" | egrep 'access\$\d+08\(' | wc -l | xargs)

    POSTDEC=$(echo "$METHODS" | egrep 'access\$\d+10\(' | wc -l | xargs)

    OTHER=$(($ACCESSORS - $METHOD_AND_READ - $WRITE - $PREINC - $PREDEC - $POSTINC - $POSTDEC))


    NAME=$(basename $1)


    echo -e "$NAME\t$ACCESSORS\t$READ\t$WRITE\t$PREINC\t$PREDEC\t$POSTINC\t$POSTDEC\t$OTHER"

    View Slide

  76. $ column -t -s $'\t' \
    <(echo -e "NAME\tTOTAL\tMETHOD/READ\tWRITE\tPREINC\tPREDEC\tPOSTINC\tPOSTDEC\tOTHER" \
    && find apks -type f | \
    xargs -L1 ./accessors.sh | \
    sort -k2,2nr)
    Warning: This may take a while to run!

    View Slide

  77. $ column -t -s $'\t' \
    <(echo -e "NAME\tTOTAL\tMETHOD/READ\tWRITE\tPREINC\tPREDEC\tPOSTINC\tPOSTDEC\tOTHER" \
    && find apks -type f | \
    xargs -L1 ./accessors.sh | \
    sort -k2,2nr)
    NAME TOTAL METHOD/READ WRITE PREINC PREDEC POSTINC POSTDEC OTHER
    com.amazon.avod.thirdpartyclient 5545 4963 506 0 0 9 5 62
    com.amazon.kindle 5245 4399 789 0 0 11 4 42
    com.amazon.mShop.android 4774 4091 593 2 0 42 6 40
    com.audible.application 4357 3782 526 0 0 7 1 41
    com.waze 4269 3544 675 0 0 18 4 28
    com.amazon.mShop.android.shopping 3587 2968 536 3 0 38 5 37
    me.lyft.android 3330 3111 200 0 1 2 1 15
    com.nhl.gc1112.free 2796 2446 316 1 2 9 5 17
    com.etrade.mobilepro.activity 2611 2327 273 0 0 2 1 8
    air.com.nbcuni.com.nbcsports.liveextra 2448 2120 305 0 0 14 2 7
    com.untappdllc.app 2314 2000 247 1 0 6 0 60
    com.paypal.android.p2pmobile 2066 1771 286 1 0 2 0 6
    com.google.android.apps.giant 1967 1747 199 0 0 6 3 12
    com.netflix.mediaclient 1963 1642 294 1 0 9 2 15
    com.stackexchange.marvin 1842 1386 260 0 0 6 2 188
    net.flixster.android 1836 1583 239 0 0 6 2 6
    com.Slack 1801 1571 215 0 0 5 2 8
    com.showtime.showtimeanytime 1727 1450 250 0 0 4 4 19
    com.google.android.apps.cloudconsole 1643 1464 168 0 0 1 2 8
    com.eventbrite.attendee 1529 1368 147 0 0 2 0 12
    org.videolan.vlc 1358 1163 151 0 0 2 1 41
    com.imdb.mobile 1353 897 92 1 0 3 1 359
    com.robinhood.android 1239 1036 149 0 0 4 0 50
    com.twitter.android 1088 957 117 0 0 5 0 9

    View Slide

  78. View Slide

  79. public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L


    private class ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G

    }"

    View Slide

  80. public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L


    private class ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G

    }"

    View Slide

  81. public class ItemsView {

    private static String displayText(String item) {

    return ""; // TODO

    }L


    private class ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G

    }"

    View Slide

  82. public class ItemsView {

    static String displayText(String item) {

    return ""; // TODO

    }L


    private class ItemsAdapter {

    void bindItem(TextView tv, String item) {

    tv.setText(ItemsView.displayText(item));

    }H

    }G

    }"

    View Slide

  83. interface Callback {

    void call(T value);

    }



    class StringCallback implements Callback {

    @Override public void call(String value) {

    System.out.println(value);

    }

    }
    // Callbacks.java

    View Slide

  84. $ javac Callbacks.java
    $ javap StringCallback

    View Slide

  85. $ javac Callbacks.java
    $ javap StringCallback
    class StringCallback implements Callback {
    StringCallback();
    public void call(java.lang.String);
    public void call(java.lang.Object);
    }
    -c

    View Slide

  86. $ javap -c StringCallback

    View Slide

  87. $ javap -c StringCallback
    class StringCallback implements Callback {
    StringCallback();
    Code:
    public void call(java.lang.String);
    Code:
    public void call(java.lang.Object);
    Code:
    0: aload_0
    1: aload_1
    2: checkcast #4 // class java/lang/String
    5: invokevirtual #5 // Method call:(Ljava/lang/String;)V
    8: return
    }

    View Slide

  88. $ javap -c StringCallback
    class StringCallback implements Callback {
    StringCallback();
    Code:
    public void call(java.lang.String);
    Code:
    public void call(java.lang.Object);
    Code:
    0: aload_0
    1: aload_1
    2: checkcast #4 // class java/lang/String
    5: invokevirtual #5 // Method call:(Ljava/lang/String;)V
    8: return
    }

    View Slide

  89. // Providers.java






    class ViewProvider implements Provider {

    @Override public View get(Context context) {

    return new View(context);

    }

    }


    interface Provider {

    T get(Context context);

    }

    View Slide

  90. $ javac -bootclasspath android-sdk/platforms/android-24/android.jar \
    Example.java
    $ javap -c ViewProvider
    class ViewProvider implements Provider {
    ViewProvider();
    Code:
    public android.view.View get(android.content.Context);
    Code:
    public java.lang.Object get(android.content.Context);
    Code:
    0: aload_0
    1: aload_1
    2: invokevirtual #4 // Method get:(…)Landroid/view/View;
    5: areturn
    }

    View Slide

  91. $ javac -bootclasspath android-sdk/platforms/android-24/android.jar \
    Example.java
    $ javap -c ViewProvider
    class ViewProvider implements Provider {
    ViewProvider();
    Code:
    public android.view.View get(android.content.Context);
    Code:
    public java.lang.Object get(android.content.Context);
    Code:
    0: aload_0
    1: aload_1
    2: invokevirtual #4 // Method get:(…)Landroid/view/View;
    5: areturn
    }

    View Slide

  92. // Providers.java






    class ViewProvider implements Provider {

    @Override public View get(Context context) {

    return new View(context);

    }2

    }3


    interface Provider {

    T get(Context context);

    }

    View Slide

  93. class ViewProvider implements Provider {

    @Override public View get(Context context) {

    return new View(context);

    }2

    }3
    class TextViewProvider extends ViewProvider {

    @Override public TextView get(Context context) {

    return new TextView(context);

    }

    }

    View Slide

  94. class ViewProvider implements Provider {

    @Override public View get(Context context) {

    return new View(context);

    }

    }
    class TextViewProvider extends ViewProvider {

    @Override public TextView get(Context context) {

    return new TextView(context);

    }

    }

    View Slide

  95. $ javap TextViewProvider
    class TextViewProvider extends ViewProvider {
    TextViewProvider();
    public android.widget.TextView get(android.content.Context);
    public android.view.View get(android.content.Context);
    public java.lang.Object get(android.content.Context);
    }

    View Slide

  96. #!/usr/bin/python


    import os

    import subprocess

    import sys


    list = subprocess.check_output(["dex-method-list", sys.argv[1]])


    class_info_by_name = {}


    for item in list.split('\n'):

    first_space = item.find(' ')

    open_paren = item.find('(')

    close_paren = item.find(')')

    last_space = item.rfind(' ')


    class_name = item[0:first_space]

    method_name = item[first_space + 1:open_paren]

    params = [param for param in item[open_paren + 1:close_paren].split(', ') if len(param) > 0]

    return_type = item[last_space + 1:]

    if last_space < close_paren:

    return_type = 'void'


    # print class_name, method_name, params, return_type


    if class_name not in class_info_by_name:

    class_info_by_name[class_name] = {}

    class_info = class_info_by_name[class_name]


    if method_name not in class_info:

    class_info[method_name] = []

    method_info_by_name = class_info[method_name]


    method_info_by_name.append({

    'params': params,

    'return': return_type

    })


    count = 0

    for class_name, class_info in class_info_by_name.items():

    for method_name, method_info_by_name in class_info.items():

    for method_info in method_info_by_name:

    for other_method_info in method_info_by_name:

    if method_info == other_method_info:

    continue # Do not compare against self.

    params = method_info['params']

    other_params = other_method_info['params']

    if len(params) != len(other_params):

    continue # Do not compare different numbered parameter lists.


    match = True

    erased = False

    for idx, param in enumerate(params):

    other_param = other_params[idx]

    if param != 'Object' and not param[0].islower() and other_param == 'Object':

    erased = True

    elif param != other_param:

    match = False


    return_type = method_info['return']

    other_return_type = other_method_info['return']

    if return_type != 'Object' and other_return_type == 'Object':

    erased = True

    elif return_type != other_return_type:

    match = False


    if match and erased:

    count += 1

    # print "FOUND! %s %s %s %s" % (class_name, method_name, params, return_type)

    # print " %s %s %s %s" % (class_name, method_name, other_params, other_return_type)


    print os.path.basename(sys.argv[1]) + '\t' + str(count)
    erased.py

    View Slide

  97. $ column -t -s $'\t' \
    <(echo -e "NAME\tERASED" \
    && find apks -type f | \
    xargs -L1 ./erased.py | \
    sort -k2,2nr)
    Warning: This may take a while to run!

    View Slide

  98. $ column -t -s $'\t' \
    <(echo -e "NAME\tERASED" \
    && find apks -type f | \
    xargs -L1 ./erased.py | \
    sort -k2,2nr)
    NAME ERASED
    com.amazon.mShop.android 4387
    me.lyft.android 3269
    com.amazon.avod.thirdpartyclient 2564
    com.amazon.kindle 2439
    com.imdb.mobile 2375
    com.amazon.mShop.android.shopping 2259
    com.nhl.gc1112.free 2178
    com.Slack 2041
    com.google.android.apps.giant 1971
    com.ubercab 1877
    com.squareup.cash 1819
    com.twitter.android 1777
    air.com.nbcuni.com.nbcsports.liveextra 1415
    com.google.android.apps.docs.editors.slides 1378
    com.audible.application 1206
    com.robinhood.android 1196
    com.foursquare.robin 1165
    com.joelapenna.foursquared 1095
    com.untappdllc.app 1091
    com.google.android.apps.cloudconsole 1040
    com.eventbrite.attendee 897

    View Slide

  99. class Greeter {

    void sayHi() {

    System.out.println("Hi!");

    }1

    }2




    class Example {

    public static void main(String... args) {
    Executor executor = Executors.newSingleThreadExecutor();

    Greeter greeter = new Greeter();

    }5

    }6

    View Slide

  100. class Greeter {

    void sayHi() {

    System.out.println("Hi!");

    }1

    }2
    class Example {

    public static void main(String... args) {
    Executor executor = Executors.newSingleThreadExecutor();

    final Greeter greeter = new Greeter();

    executor.execute(new Runnable() {

    @Override public void run() {

    greeter.sayHi();

    }4

    });

    }5

    }6

    View Slide

  101. class Greeter {

    void sayHi() {

    System.out.println("Hi!");

    }1

    }2
    class Example {

    public static void main(String... args) {
    Executor executor = Executors.newSingleThreadExecutor();

    Greeter greeter = new Greeter();

    executor.execute(() -> greeter.sayHi());

    }5

    }6

    View Slide

  102. class Greeter {

    void sayHi() {

    System.out.println("Hi!");

    }1

    }2
    class Example {

    public static void main(String... args) {
    Executor executor = Executors.newSingleThreadExecutor();

    Greeter greeter = new Greeter();

    executor.execute(greeter::sayHi);

    }5

    }6

    View Slide

  103. $ javac *.java
    Retrolambda toolchain
    $ java -Dretrolambda.inputDir=. -Dretrolambda.classpath=. \

    -jar retrolambda.jar

    $ dx --dex --output=example.dex *.class

    $ dex-method-list example.dex

    View Slide

  104. $ javac *.java
    Retrolambda toolchain
    $ java -jar android-sdk/build-tools/24.0.1/jack.jar \

    -cp android-sdk/platforms/android-24/android.jar \

    --output-dex . *.java
    Jack toolchain
    $ java -Dretrolambda.inputDir=. -Dretrolambda.classpath=. \

    -jar retrolambda.jar

    $ dx --dex --output=example.dex *.class

    $ dex-method-list example.dex


    $ dex-method-list classes.dex

    View Slide

  105. Code
    Retrolambda
    2.1.0
    Retrolambda
    2.3.0
    Jack
    24.0.1

    View Slide

  106. Code
    Retrolambda
    2.1.0
    Retrolambda
    2.3.0
    Jack
    24.0.1
    new Runnable() {

    @Override
    public void run() {

    greeter.sayHi();

    }

    }
    2 2 2

    View Slide

  107. Example ()
    Example main(String[])
    Example run(Runnable)
    Example$1 (Greeter)
    Example$1 run()
    Greeter ()
    Greeter sayHi()
    java.io.PrintStream println(String)
    java.lang.Object ()
    java.lang.Runnable run()

    View Slide

  108. Example ()
    Example main(String[])
    Example run(Runnable)
    Example$1 (Greeter)
    Example$1 run()
    Greeter ()
    Greeter sayHi()
    java.io.PrintStream println(String)
    java.lang.Object ()
    java.lang.Runnable run()

    View Slide

  109. Example$1 (Greeter)
    Example$1 run()

    View Slide

  110. Example$1 (Greeter)
    Example$1 run()
    $ javap -c 'Example$1'
    final class Example$1 implements java.lang.Runnable {
    Example$1(Greeter);
    Code:
    public void run();
    Code:
    0: aload_0
    1: getfield #1 // Field val$greeter:LGreeter;
    4: invokevirtual #3 // Method Greeter.sayHi:()V
    7: return
    }

    View Slide

  111. Example$1 (Greeter)
    Example$1 run()
    $ javap -c 'Example$1'
    final class Example$1 implements java.lang.Runnable {
    Example$1(Greeter);
    Code:
    public void run();
    Code:
    0: aload_0
    1: getfield #1 // Field val$greeter:LGreeter;
    4: invokevirtual #3 // Method Greeter.sayHi:()V
    7: return
    }

    View Slide

  112. Code
    Retrolambda
    2.1.0
    Retrolambda
    2.3.0
    Jack
    24.0.1
    new Runnable() {

    @Override
    public void run() {

    greeter.sayHi();

    }

    }
    2 2 2

    View Slide

  113. Code
    Retrolambda
    2.1.0
    Retrolambda
    2.3.0
    Jack
    24.0.1
    new Runnable() {

    @Override
    public void run() {

    greeter.sayHi();

    }

    }
    2 2 2
    () -> greeter.sayHi() 6 or 7 4 3

    View Slide

  114. Example ()
    Example lambda$main$0(Greeter)
    Example main(String[])
    Example run(Runnable)
    Example$$Lambda$1 (Greeter)
    Example$$Lambda$1 lambdaFactory$(Greeter) → Runnable
    Example$$Lambda$1 run()
    Greeter ()
    Greeter sayHi()
    java.io.PrintStream println(String)
    java.lang.Object ()
    java.lang.Runnable run()
    Retrolambda

    View Slide

  115. Example ()
    Example lambda$main$0(Greeter)
    Example main(String[])
    Example run(Runnable)
    Example$$Lambda$1 (Greeter)
    Example$$Lambda$1 lambdaFactory$(Greeter) → Runnable
    Example$$Lambda$1 run()
    Greeter ()
    Greeter sayHi()
    java.io.PrintStream println(String)
    java.lang.Object ()
    java.lang.Runnable run()
    Retrolambda

    View Slide

  116. Example lambda$main$0(Greeter)
    Example$$Lambda$1 (Greeter)
    Example$$Lambda$1 lambdaFactory$(Greeter) → Runnable
    Example$$Lambda$1 run()
    Retrolambda

    View Slide

  117. Example lambda$main$0(Greeter)
    Example$$Lambda$1 (Greeter)
    Example$$Lambda$1 lambdaFactory$(Greeter) → Runnable
    Example$$Lambda$1 run()
    Retrolambda
    $ javap -c Example
    class Example {
    static void lambda$main$0(Greeter);
    Code:
    0: aload_0
    1: invokespecial #45 // Method sayHi:()V
    4: return
    }

    View Slide

  118. Retrolambda
    Example lambda$main$0(Greeter)
    Example$$Lambda$1 (Greeter)
    Example$$Lambda$1 lambdaFactory$(Greeter) → Runnable
    Example$$Lambda$1 run()
    $ javap -c Example
    class Example {
    static void lambda$main$0(Greeter);
    Code:
    0: aload_0
    1: invokespecial #45 // Method sayHi:()V
    4: return
    }

    View Slide

  119. Example lambda$main$0(Greeter)
    Example$$Lambda$1 (Greeter)
    Example$$Lambda$1 lambdaFactory$(Greeter) → Runnable
    Example$$Lambda$1 run()
    Retrolambda
    $ javap -c 'Example$$Lambda$1'
    final class Example$$Lambda$1 implements java.lang.Runnable {
    public void run();
    Code:
    0: aload_0
    1: getfield #15 // Field arg$1:LGreeter;
    4: invokestatic #21 // Method Example.lambda$main$0:
    7: return
    }

    View Slide

  120. Example lambda$main$0(Greeter)
    Example$$Lambda$1 (Greeter)
    Example$$Lambda$1 lambdaFactory$(Greeter) → Runnable
    Example$$Lambda$1 run()
    Retrolambda
    $ javap -c 'Example$$Lambda$1'
    final class Example$$Lambda$1 implements java.lang.Runnable {
    public void run();
    Code:
    0: aload_0
    1: getfield #15 // Field arg$1:LGreeter;
    4: invokestatic #21 // Method Example.lambda$main$0:
    7: return
    }

    View Slide

  121. Example lambda$main$0(Greeter)
    Example$$Lambda$1 (Greeter)
    Example$$Lambda$1 lambdaFactory$(Greeter) → Runnable
    Example$$Lambda$1 run()
    Retrolambda

    View Slide

  122. Example -Example_lambda$1(Greeter)
    Example ()
    Example main(String[])
    Example run(Runnable)
    Example$-void_main_java_lang_String__args_LambdaImpl0 (Greeter)
    Example$-void_main_java_lang_String__args_LambdaImpl0 run()
    Greeter ()
    Greeter sayHi()
    java.io.PrintStream println(String)
    java.lang.Object ()
    java.lang.Runnable run()
    Jack

    View Slide

  123. Example -Example_lambda$1(Greeter)
    Example ()
    Example main(String[])
    Example run(Runnable)
    Example$-void_main_java_lang_String__args_LambdaImpl0 (Greeter)
    Example$-void_main_java_lang_String__args_LambdaImpl0 run()
    Greeter ()
    Greeter sayHi()
    java.io.PrintStream println(String)
    java.lang.Object ()
    java.lang.Runnable run()
    Jack

    View Slide

  124. Example -Example_lambda$1(Greeter)
    Example$-void_main_java_lang_String__args_LambdaImpl0 (Greeter)
    Example$-void_main_java_lang_String__args_LambdaImpl0 run()
    Jack

    View Slide

  125. Code
    Retrolambda
    2.1.0
    Retrolambda
    2.3.0
    Jack
    24.0.1
    new Runnable() {

    @Override
    public void run() {

    greeter.sayHi();

    }

    }
    2 2 2
    () -> greeter.sayHi() 6 or 7 4 3

    View Slide

  126. Code
    Retrolambda
    2.1.0
    Retrolambda
    2.3.0
    Jack
    24.0.1
    new Runnable() {

    @Override
    public void run() {

    greeter.sayHi();

    }

    }
    2 2 2
    () -> greeter.sayHi() 6 or 7 4 3
    greeter::sayHi 4 3 or 4 3

    View Slide

  127. lambdas.sh
    #!/bin/bash

    set -e


    ALL=$(dex-method-list $1)


    RL=$(echo "$ALL" | \grep ' lambda\$' | wc -l | xargs)

    JACK=$(echo "$ALL" | \grep '_lambda\$' | wc -l | xargs)


    NAME=$(basename $1)


    echo -e "$NAME\t$RL\t$JACK"

    View Slide

  128. $ column -t -s $'\t' \
    <(echo -e "NAME\tRETROLAMBDA\tJACK" \
    && find apks -type f | \
    xargs -L1 ./lambdas.sh | \
    sort -k2,2nr)
    Warning: This may take a while to run!

    View Slide

  129. $ column -t -s $'\t' \
    <(echo -e "NAME\tRETROLAMBDA\tJACK" \
    && find apks -type f | \
    xargs -L1 ./lambdas.sh | \
    sort -k2,2nr)
    NAME RETROLAMBDA JACK
    com.squareup.cash 826 0
    com.robinhood.android 680 0
    com.imdb.mobile 306 0
    com.stackexchange.marvin 174 0
    com.eventbrite.attendee 53 0
    com.untappdllc.app 53 0

    View Slide

  130. HashMap
    HashSet
    HashMap
    HashMap
    HashMap
    HashMap
    HashMap
    HashMap

    View Slide

  131. HashMap
    HashSet
    HashMap
    HashMap
    HashMap
    HashMap
    HashMap
    HashMap
    ArrayMap
    ArraySet
    SparseArray
    SparseBooleanArray
    SparseIntArray
    SparseLongArray
    LongSparseArray

    View Slide

  132. HashMap

    View Slide

  133. HashMap
    int put(Integer, V)

    View Slide

  134. HashMap
    int put(Integer, V)
    getKey() int

    View Slide

  135. HashMap
    int Integer.valueOf put(Integer, V)
    getKey() int
    Integer.intValue

    View Slide

  136. HashMap
    Node[] table;
    int size;

    View Slide

  137. HashMap
    Node[] table;
    int size;
    ...

    View Slide

  138. HashMap
    Node[] table;
    int size;
    ...
    Node
    int hash;

    K key;

    V value;

    Node next;

    View Slide

  139. HashMap
    Node[] table;
    int size;
    ...
    Node
    int hash;

    K key;

    V value;

    Node next;

    View Slide

  140. HashMap
    Node[] table;
    int size;
    ...
    Node
    int hash;

    K key;

    V value;

    Node next;
    Node
    int hash;

    K key;

    V value;

    Node next;

    View Slide

  141. $ java -jar jol-cli-0.5-full.jar internals java.util.HashMap

    View Slide

  142. $ java -jar jol-cli-0.5-full.jar internals java.util.HashMap
    # Running 64-bit HotSpot VM.
    # Objects are 8 bytes aligned.
    java.util.HashMap object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 4 (object header) 01 00 00 00
    4 4 (object header) 00 00 00 00
    8 4 (object header) 9f 37 00 f8
    12 4 Set AbstractMap.keySet null
    16 4 Collection AbstractMap.values null
    20 4 int HashMap.size 0
    24 4 int HashMap.modCount 0
    28 4 int HashMap.threshold 0
    32 4 float HashMap.loadFactor 0.75
    36 4 Node[] HashMap.table null
    40 4 Set HashMap.entrySet null
    44 4 (loss due to the next object alignment)
    Instance size: 48 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

    View Slide

  143. $ java -jar jol-cli-0.5-full.jar internals java.util.HashMap
    # Running 64-bit HotSpot VM.
    # Objects are 8 bytes aligned.
    java.util.HashMap object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 4 (object header) 01 00 00 00
    4 4 (object header) 00 00 00 00
    8 4 (object header) 9f 37 00 f8
    12 4 Set AbstractMap.keySet null
    16 4 Collection AbstractMap.values null
    20 4 int HashMap.size 0
    24 4 int HashMap.modCount 0
    28 4 int HashMap.threshold 0
    32 4 float HashMap.loadFactor 0.75
    36 4 Node[] HashMap.table null
    40 4 Set HashMap.entrySet null
    44 4 (loss due to the next object alignment)
    Instance size: 48 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

    View Slide

  144. $ java -jar jol-cli-0.5-full.jar internals 'java.util.HashMap$Node'

    View Slide

  145. $ java -jar jol-cli-0.5-full.jar internals 'java.util.HashMap$Node'
    # Running 64-bit HotSpot VM.
    # Objects are 8 bytes aligned.
    java.util.HashMap$Node object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 12 (object header) N/A
    12 4 int Node.hash N/A
    16 4 Object Node.key N/A
    20 4 Object Node.value N/A
    24 4 Node Node.next N/A
    28 4 (loss due to the next object alignment)
    Instance size: 32 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

    View Slide

  146. $ java -jar jol-cli-0.5-full.jar internals 'java.util.HashMap$Node'
    # Running 64-bit HotSpot VM.
    # Objects are 8 bytes aligned.
    java.util.HashMap$Node object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 12 (object header) N/A
    12 4 int Node.hash N/A
    16 4 Object Node.key N/A
    20 4 Object Node.value N/A
    24 4 Node Node.next N/A
    28 4 (loss due to the next object alignment)
    Instance size: 32 bytes
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

    View Slide

  147. HashMap
    Node[] table;
    int size;
    Node
    int hash;

    K key;

    V value;

    Node next;

    View Slide

  148. HashMap
    Node[] table;
    int size;
    Node
    int hash;

    K key;

    V value;

    Node next;
    48
    HashMap object

    View Slide

  149. HashMap
    Node[] table;
    int size;
    Node
    int hash;

    K key;

    V value;

    Node next;
    48 + 32 * entries
    HashMap object
    Node objects

    View Slide

  150. HashMap
    Node[] table;
    int size;
    Node
    int hash;

    K key;

    V value;

    Node next;
    48 + 32 * entries + 4 * (entries / loadFactor) + 8
    HashMap object
    array of Node in HashMap
    Node objects

    View Slide

  151. SparseArray
    int[] keys;
    V[] values;
    int size;

    View Slide

  152. SparseArray
    int[] keys;
    V[] values;
    int size;
    ...

    View Slide

  153. SparseArray
    int[] keys;
    V[] values;
    int size;
    ...
    ...

    View Slide

  154. SparseArray
    int[] keys;
    V[] values;
    int size;
    ...
    ...

    View Slide

  155. $ javac SparseArray.java
    $ java -cp .:jol-cli-0.5-full.jar org.openjdk.jol.Main \

    internals android.util.SparseArray

    View Slide

  156. $ javac SparseArray.java
    $ java -cp .:jol-cli-0.5-full.jar org.openjdk.jol.Main \

    internals android.util.SparseArray
    # Running 64-bit HotSpot VM.
    # Objects are 8 bytes aligned.
    android.util.SparseArray object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 4 (object header) 01 00 00 00
    4 4 (object header) 00 00 00 00
    8 4 (object header) 1a 69 01 f8
    12 4 int SparseArray.mSize 0
    16 1 boolean SparseArray.mGarbage false
    17 3 (alignment/padding gap) N/A
    20 4 int[] SparseArray.mKeys [0, 0, 0, 0, 0, 0, …]
    24 4 Object[] SparseArray.mValues [null, null, null, …]
    28 4 (loss due to the next object alignment)
    Instance size: 32 bytes
    Space losses: 3 bytes internal + 4 bytes external = 7 bytes total

    View Slide

  157. $ javac SparseArray.java
    $ java -cp .:jol-cli-0.5-full.jar org.openjdk.jol.Main \

    internals android.util.SparseArray
    # Running 64-bit HotSpot VM.
    # Objects are 8 bytes aligned.
    android.util.SparseArray object internals:
    OFFSET SIZE TYPE DESCRIPTION VALUE
    0 4 (object header) 01 00 00 00
    4 4 (object header) 00 00 00 00
    8 4 (object header) 1a 69 01 f8
    12 4 int SparseArray.mSize 0
    16 1 boolean SparseArray.mGarbage false
    17 3 (alignment/padding gap) N/A
    20 4 int[] SparseArray.mKeys [0, 0, 0, 0, 0, 0, …]
    24 4 Object[] SparseArray.mValues [null, null, null, …]
    28 4 (loss due to the next object alignment)
    Instance size: 32 bytes
    Space losses: 3 bytes internal + 4 bytes external = 7 bytes total

    View Slide

  158. SparseArray
    int[] keys;
    V[] values;
    int size;

    View Slide

  159. SparseArray
    int[] keys;
    V[] values;
    int size;
    32
    SparseArray object

    View Slide

  160. SparseArray
    int[] keys;
    V[] values;
    int size;
    32 + 4 * entries
    SparseArray object
    array of int keys

    View Slide

  161. SparseArray
    int[] keys;
    V[] values;
    int size;
    32 + 4 * entries + 4 * entries
    SparseArray object
    array of int keys array of V values

    View Slide

  162. SparseArray
    int[] keys;
    V[] values;
    int size;
    32 + (4 * entries + 4 * entries) / 0.75
    SparseArray object
    array of int keys array of V values binary tree fudge factor

    View Slide

  163. SparseArray
    32 + (4 * entries + 4 * entries) / 0.75
    HashMap
    48 + 32 * entries + 4 * (entries / loadFactor) + 8

    View Slide

  164. SparseArray
    32 + (4 * entries + 4 * entries) / 0.75
    HashMap
    48 + 32 * entries + 4 * (entries / 0.75) + 8

    View Slide

  165. SparseArray
    32 + (4 * 50 + 4 * 50) / 0.75
    HashMap
    48 + 32 * 50 + 4 * (50 / 0.75) + 8

    View Slide

  166. SparseArray
    32 + (4 * 50 + 4 * 50) / 0.75 = 656
    HashMap
    48 + 32 * 50 + 4 * (50 / 0.75) + 8 = 1922

    View Slide

  167. TODO (for you!)
    • Turn on "private member" inspection in the IDE and listen to it.

    View Slide

  168. TODO (for you!)
    • Turn on "private member" inspection in the IDE and listen to it.
    • Report synthetic accessor methods in libraries as bugs.

    View Slide

  169. TODO (for you!)
    • Turn on "private member" inspection in the IDE and listen to it.
    • Report synthetic accessor methods in libraries as bugs.
    • Update Retrolambda to 2.3.0 and try not to use it in open source libraries.

    View Slide

  170. TODO (for you!)
    • Turn on "private member" inspection in the IDE and listen to it.
    • Report synthetic accessor methods in libraries as bugs.
    • Update Retrolambda to 2.3.0 and try not to use it in open source libraries.
    • Try using the Jack compiler in your app. Report failures to b.android.com.

    View Slide

  171. TODO (for you!)
    • Turn on "private member" inspection in the IDE and listen to it.
    • Report synthetic accessor methods in libraries as bugs.
    • Update Retrolambda to 2.3.0 and try not to use it in open source libraries.
    • Try using the Jack compiler in your app. Report failures to b.android.com.
    • Use ProGuard without overly-matchy rules (-keep class com.foo.**).

    View Slide

  172. Additional Presentations

    View Slide

  173. http://jakes.link/eliminate-overhead

    View Slide

  174. http://jakes.link/dex-ed

    View Slide

  175. http://jakes.link/android-perf

    View Slide

  176. Links
    • Jack generates extra method for method references

    http://b.android.com/218301
    • Retrolambda generates extra method for lambdas / method references

    https://github.com/orfjackal/retrolambda/issues/81
    • dex-method-list tool for showing methods in class/jar/aar/dex/apk

    https://github.com/JakeWharton/dex-method-list
    • Java Object Layout ("jol") tool for showing memory cost of types

    http://openjdk.java.net/projects/code-tools/jol/
    • accessors.sh, erased.py, lambdas.sh helper scripts

    http://jakes.link/exploring-scripts

    View Slide

  177. Jake Wharton
    Exploring
    Java Hidden
    Costs

    View Slide