最近、Lucas Eder は 、1つの要素からリストの不要なクロールを削除するために、Java JITコンパイラーがそのようなコードを最適化できるかどうかに関するブログに興味を持ちました 。
// ... "",
for (Object object : Collections.singletonList("abc")) {
doSomethingWith(object);
}
: JIT . HotSpot JVM 64 bit . , :
static int testIterator(List<String> list) {
int sum = 0;
for (String s : list) {
sum += s.length();
}
return sum;
}
Java- , :
static int testIterator(List<String> list) {
int sum = 0;
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String s = it.next();
sum += s.length();
}
return sum;
}
, list
JIT- iterator()
, hasNext()
next()
, , , . , , singletonList
? main()
:
public class Test {
static int res = 0;
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
res += testIterator(Collections.singletonList("x"));
}
System.out.println(res);
}
}
testIterator
, JIT- C2. , HotSpot JIT-: C1 () C2 (). 64- Java 8 . C1 ( , ). , ( ""). , , , . . JVM , list
. , 100% Collections$SingletonList ( singletonList
).
, C2, . C2 , SingletonList
, . , iterator()
singletonIterator(). , , , hasNext
, , , NoSuchElementException
. C2 ?
, JIT- . hsdis. JITWatch JMH- -perfasm
. , :
$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintAssembly Test >output.txt
: . , , testIterator
. C2 Intel x64 4 :
# {method} {0x0000000055120518} 'testIterator' '(Ljava/util/List;)I' in 'Test'
# parm0: rdx:rdx = 'java/util/List'
# [sp+0x20] (sp of caller)
0x00000000028e7560: mov %eax,-0x6000(%rsp)
0x00000000028e7567: push %rbp
0x00000000028e7568: sub $0x10,%rsp ;*synchronization entry
; - Test::testIterator@-1 (line 15)
0x00000000028e756c: mov 0x8(%rdx),%r10d ; implicit exception: dispatches to 0x00000000028e75bd
0x00000000028e7570: cmp $0x14d66a20,%r10d ; {metadata('java/util/Collections$SingletonList')}
0x00000000028e7577: jne 0x00000000028e75a0 ;*synchronization entry
; - java.util.Collections::singletonIterator@-1
; - java.util.Collections$SingletonList::iterator@4
; - Test::testIterator@3 (line 16)
0x00000000028e7579: mov 0x10(%rdx),%ebp ;*getfield element
; - java.util.Collections$SingletonList::iterator@1
; - Test::testIterator@3 (line 16)
0x00000000028e757c: mov 0x8(%rbp),%r11d ; implicit exception: dispatches to 0x00000000028e75c9
0x00000000028e7580: cmp $0x14d216d0,%r11d ; {metadata('java/lang/String')}
0x00000000028e7587: jne 0x00000000028e75b1
0x00000000028e7589: mov %rbp,%r10 ;*checkcast
; - Test::testIterator@24 (line 16)
0x00000000028e758c: mov 0xc(%r10),%r10d ;*getfield value
; - java.lang.String::length@1
; - Test::testIterator@30 (line 17)
0x00000000028e7590: mov 0xc(%r10),%eax ;*synchronization entry
; - Test::testIterator@-1 (line 15)
; implicit exception: dispatches to 0x00000000028e75d5
0x00000000028e7594: add $0x10,%rsp
0x00000000028e7598: pop %rbp
0x00000000028e7599: test %eax,-0x27b759f(%rip) # 0x0000000000130000
; {poll_return}
0x00000000028e759f: retq
... //
, — . , :
// - JIT-
mov %eax,-0x6000(%rsp)
push %rbp
sub $0x10,%rsp
// list ( rdx).
// 0x8. list.getClass().
// null. , null,
// .
// NullPointerException
mov 0x8(%rdx),%r10d
// list.getClass() Collections$SingletonList.
// JVM , , JIT ,
cmp $0x14d66a20,%r10d
// list - SingletonList,
jne 0x00000000028e75a0
// Collections$SingletonList.element rbp. 64-,
// 4 32 , 32 ebp
mov 0x10(%rdx),%ebp
// String ( , )
mov 0x8(%rbp),%r11d
cmp $0x14d216d0,%r11d
// - , ( ClassCastException)
jne 0x00000000028e75b1
// String.value r10. char[],
mov %rbp,%r10
mov 0xc(%r10),%r10d
// eax,
mov 0xc(%r10),%eax
//
add $0x10,%rsp
pop %rbp
// safe-point. JVM , , .
test %eax,-0x27b759f(%rip)
//
retq
- , :
if (list.class != Collections$SingletonList) {
goto SLOW_PATH;
}
str = ((Collections$SingletonList)list).element;
if (str.class != String) {
goto EXCEPTIONAL_PATH;
}
return ((String)str).value.length;
? , , . ( , ). JIT- , , , , , hasNext
, , ! sum
. , . , singletonList
, - , (, , ). . null
list
( type erasure) — .
, ? , singletonList
. . , , JIT- , singletonList
. , , , . JIT : , .