Comme déjà souligné, le compilateur JIT (juste à temps) peut optimiser une boucle vide afin de supprimer les itérations inutiles. Mais comment?
En fait, il existe deux compilateurs JIT: C1 et C2 . Tout d'abord, le code est compilé avec le C1. C1 collecte les statistiques et aide la JVM à découvrir que dans 100% des cas notre boucle vide ne change rien et est inutile. Dans cette situation, C2 entre en scène. Lorsque le code est appelé très souvent, il peut être optimisé et compilé avec le C2 à l'aide des statistiques collectées.
À titre d'exemple, je vais tester le prochain extrait de code (mon JDK est défini sur slowdebug build 9-internal ):
public class Demo {
private static void run() {
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
}
System.out.println("Done!");
}
}
Avec les options de ligne de commande suivantes:
-XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*Demo.run
Et il existe différentes versions de ma méthode run , compilées avec les C1 et C2 de manière appropriée. Pour moi, la variante finale (C2) ressemble à ceci:
...
; B1: # B3 B2 <- BLOCK HEAD IS JUNK Freq: 1
0x00000000125461b0: mov dword ptr [rsp+0ffffffffffff7000h], eax
0x00000000125461b7: push rbp
0x00000000125461b8: sub rsp, 40h
0x00000000125461bc: mov ebp, dword ptr [rdx]
0x00000000125461be: mov rcx, rdx
0x00000000125461c1: mov r10, 57fbc220h
0x00000000125461cb: call indirect r10 ; *iload_1
0x00000000125461ce: cmp ebp, 7fffffffh ; 7fffffff => 2147483647
0x00000000125461d4: jnl 125461dbh ; jump if not less
; B2: # B3 <- B1 Freq: 0.999999
0x00000000125461d6: mov ebp, 7fffffffh ; *if_icmpge
; B3: # N44 <- B1 B2 Freq: 1
0x00000000125461db: mov edx, 0ffffff5dh
0x0000000012837d60: nop
0x0000000012837d61: nop
0x0000000012837d62: nop
0x0000000012837d63: call 0ae86fa0h
...
C'est un peu brouillon, mais si vous regardez de près, vous remarquerez peut-être qu'il n'y a pas de longue boucle en cours ici. Il y a 3 blocs: B1, B2 et B3 et les étapes d'exécution peuvent être B1 -> B2 -> B3
ou B1 -> B3
. Où Freq: 1
- fréquence estimée normalisée d'exécution d'un bloc.
javap -v
pour voir.