Presentation about bytecode and what is going on at the JVM at AndroidMakers conference Paris. Fine-tuned information from my presentation at 360|AnDev Denver.
37. add r01, r02, r01
add r01, r03, r01
add r01, r04, r01
mul r07, r05, #2
add r01, r07, r01
mul r08, r06, r06
add r02, r08, r01
j = j + i + k + w + h * 2 + p * p;
r01: i
r02: j
r03: k
r04: w
r05: h
r06: p
38. Java VM (JVM)
Only the JVM knows the
architecture where is running.
In our previous example, we used up to
8 registers, but some CPUs might have
less than 8 registers…
73. Autoboxing
This is what that code is actually doing:
Long total = Long.valueOf(0);
for(Integer i = Integer.valueOf(0);
i.intValue() < N;
i = Integer.valueOf(i.intValue() + 1)) {
total = Long.valueOf(total.longValue() + (long)i.intValue())
}
74. Autoboxing
Object creation
Long total = Long.valueOf(0);
for(Integer i = Integer.valueOf(0);
i.intValue() < N;
i = Integer.valueOf(i.intValue() + 1)) {
total = Long.valueOf(total.longValue() + (long)i.intValue())
}
91. Loops - List
ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
92. ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
07: lload_0
08: getstatic list
11: iload_2
12: invokevirtual java/util/ArrayList.get
15: checkcast java/lang/Integer
18: invokevirtual java/lang/Integer.intValue
21: i2l
22: ladd
23: lstore_0
24: iinc 2, 1
27: iload_2
28: getstatic list
31: invokevirtual java/util/ArrayList.size
34: if_icmplt 7
Loops - List
93. ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
Loops - List 07: lload_0
08: getstatic list
11: iload_2
12: invokevirtual java/util/ArrayList.get
15: checkcast java/lang/Integer
18: invokevirtual java/lang/Integer.intValue
21: i2l
22: ladd
23: lstore_0
24: iinc 2, 1
27: iload_2
28: getstatic list
31: invokevirtual java/util/ArrayList.size
34: if_icmplt 7
94. ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
Loops - List 07: lload_0
08: getstatic list
11: iload_2
12: invokevirtual java/util/ArrayList.get
15: checkcast java/lang/Integer
18: invokevirtual java/lang/Integer.intValue
21: i2l
22: ladd
23: lstore_0
24: iinc 2, 1
27: iload_2
28: getstatic list
31: invokevirtual java/util/ArrayList.size
34: if_icmplt 7
95. ArrayList<Integer> list = new …
static long loopStandardList() {
long result = 0;
for(int i = 0; i < list.size(); i++) {
result += list.get(i);
}
return result;
}
Loops - List 07: lload_0
08: getstatic list
11: iload_2
12: invokevirtual java/util/ArrayList.get
15: checkcast java/lang/Integer
18: invokevirtual java/lang/Integer.intValue
21: i2l
22: ladd
23: lstore_0
24: iinc 2, 1
27: iload_2
28: getstatic list
31: invokevirtual java/util/ArrayList.size
34: if_icmplt 7
96. Loops - foreach
ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
97. ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
12: aload_3
13: invokeinterface java/util/Iterator.next
18: checkcast java/lang/Integer
21: invokevirtual java/lang/Integer.intValue
24: istore_2
25: lload_0
26: iload_2
27: i2l
28: ladd
29: lstore_0
30: aload_3
31: invokeinterface java/util/Iterator.hasNext
36: ifne 12
Loops - foreach
98. ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
Loops - foreach
12: aload_3
13: invokeinterface java/util/Iterator.next
18: checkcast java/lang/Integer
21: invokevirtual java/lang/Integer.intValue
24: istore_2
25: lload_0
26: iload_2
27: i2l
28: ladd
29: lstore_0
30: aload_3
31: invokeinterface java/util/Iterator.hasNext
36: ifne 12
99. ArrayList<Integer> list = new …
static long loopForeachList() {
long result = 0;
for(int v : list) {
result += v;
}
return result;
}
Loops - foreach
12: aload_3
13: invokeinterface java/util/Iterator.next
18: checkcast java/lang/Integer
21: invokevirtual java/lang/Integer.intValue
24: istore_2
25: lload_0
26: iload_2
27: i2l
28: ladd
29: lstore_0
30: aload_3
31: invokeinterface java/util/Iterator.hasNext
36: ifne 12
100. Loops - Array
static int[] array = new ...
static long loopStandardArray() {
long result = 0;
for(int i = 0; i < array.length; i++) {
result += array[i];
}
return result;
}
101. static int[] array = new ...
static long loopStandardArray() {
long result = 0;
for(int i = 0; i < array.length; i++) {
result += array[i];
}
return result;
}
07: lload_0
08: getstatic array
11: iload_2
12: iaload
13: i2l
14: ladd
15: lstore_0
16: iinc 2, 1
19: iload_2
20: getstatic array
23: arraylength
24: if_icmplt 7
Loops - Array
102. static int[] array = new ...
static long loopStandardArray() {
long result = 0;
for(int i = 0; i < array.length; i++) {
result += array[i];
}
return result;
}
Loops - Array
07: lload_0
08: getstatic array
11: iload_2
12: iaload
13: i2l
14: ladd
15: lstore_0
16: iinc 2, 1
19: iload_2
20: getstatic array
23: arraylength
24: if_icmplt 7
103. static int[] array = new ...
static long loopStandardArray() {
long result = 0;
for(int i = 0; i < array.length; i++) {
result += array[i];
}
return result;
}
Loops - Array
07: lload_0
08: getstatic array
11: iload_2
12: iaload
13: i2l
14: ladd
15: lstore_0
16: iinc 2, 1
19: iload_2
20: getstatic array
23: arraylength
24: if_icmplt 7
104. Loops - size cached
static int[] array = new ...
static long loopStandardArray () {
long result = 0;
int length = array.length;
for(int i = 0; i < length; i++) {
result += array[i];
}
return result;
}
105. static int[] array = new ...
static long loopStandardArray () {
long result = 0;
int length = array.length;
for(int i = 0; i < length; i++) {
result += array[i];
}
return result;
}
12: lload_0
13: getstatic array
16: iload_3
17: iaload
18: i2l
19: ladd
20: lstore_0
21: iinc 3, 1
24: iload_3
25: iload_2
26: if_icmplt 12
Loops - size cached
106. static int[] array = new ...
static long loopStandardArray () {
long result = 0;
int length = array.length;
for(int i = 0; i < length; i++) {
result += array[i];
}
return result;
}
Loops - size cached
12: lload_0
13: getstatic array
16: iload_3
17: iaload
18: i2l
19: ladd
20: lstore_0
21: iinc 3, 1
24: iload_3
25: iload_2
26: if_icmplt 12
107. Loops - backwards
static int[] array = new ...
static long loopStandardArray () {
long result = 0;
for(int i = array.length - 1; i >= 0; i--) {
result += array[i];
}
return result;
}
108. static int[] array = new ...
static long loopStandardArray () {
long result = 0;
for(int i = array.length - 1; i >= 0; i--) {
result += array[i];
}
return result;
}
12: lload_0
13: getstatic array
16: iload_2
17: iaload
18: i2l
19: ladd
20: lstore_0
21: iinc 2, -1
24: iload_2
25: ifge 12
Loops - backwards
109. static int[] array = new ...
static long loopStandardArray () {
long result = 0;
for(int i = array.length - 1; i >= 0; i--) {
result += array[i];
}
return result;
}
Loops - backwards
12: lload_0
13: getstatic array
16: iload_2
17: iaload
18: i2l
19: ladd
20: lstore_0
21: iinc 2, -1
24: iload_2
25: ifge 12
137. Worth it?
Only in very specific cases. And
then you’re probably using the
wrong language.
Too much effort involved…
But let D8/R8/Proguard do it for you!
154. StringBuilder
• StringBuilder.append cost is O(M) [M being the
length of appended String]
StringBuilder sb = new StringBuilder()
for(int i = 0; i < N; i++) {
sb.append(OTHER_STR);
}
str = sb.toString();
175. Tooling – PrintAssembly - JIT
-XX:+UnlockDiagnosticVMOptions
-XX:+PrintAssembly
-XX:CompileCommand=print,com.raimon.test.Test::method
Under the Hood of the JVM: From Bytecode Through the
JIT to Assembly by @alblue
http://alblue.bandlem.com/2016/09/javaone-hotspot.html
176. Additional References
Sinking your teeth into bytecode by @jakewharton
http://jakewharton.com/sinking-your-teeth-into-bytecode/
Exploring Kotlin’s hidden costs by @BladeCoder
https://medium.com/@BladeCoder/exploring-kotlins-
hidden-costs-part-1-fbb9935d9b62