17
Derleme anahtarlarında JVM specification okurum ve Dize'deki anahtar ifadesinin nasıl derlendiğiyle ilgilenmeye başladım. İşte incelenen test yöntemi (JDK1.7.0_40) 'dir:Dize derlemelerini niçin iki anahtar olarak değiştirmelisiniz
static int test(String i) {
switch (i) {
case "a": return -100;
case "45b": return 1;
case "c": return 2;
default: return -1;
}
}
Bu yöntem dize hashCode üzerinde basit lookupswitch içine derlenmiş bekliyoruz
ancak
static int test(java.lang.String);
Code:
0: aload_0
1: astore_1
2: iconst_m1
3: istore_2
4: aload_1
5: invokevirtual #6 // Method java/lang/String.hashCode:()I
8: lookupswitch { // 3
97: 44
99: 72
51713: 58
default: 83
}
44: aload_1
45: ldc #7 // String a
47: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
50: ifeq 83
53: iconst_0
54: istore_2
55: goto 83
58: aload_1
59: ldc #9 // String 45b
61: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
64: ifeq 83
67: iconst_1
68: istore_2
69: goto 83
72: aload_1
73: ldc #10 // String c
75: invokevirtual #8 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
78: ifeq 83
81: iconst_2
82: istore_2
83: iload_2
84: tableswitch { // 0 to 2
0: 112
1: 115
2: 117
default: 119
}
112: bipush -100
114: ireturn
115: iconst_1
116: ireturn
117: iconst_2
118: ireturn
119: iconst_m1
120: ireturn
Gördüğünüz gibi aniden
, İlk arama anahtarının dallarında JVM, bunun yerine sonraki tablo için gerçek iş üreten indeksleri yapmıyor (satır 84).Tablo düğmesi hızlı çalışmalı, bu yüzden çok fazla iş getirmeyin. Ama neyse, ek anahtar oluşturma amacı nedir?
Güncelleştirme
hashCode çakışmalarının olasılığını anlıyorum. Söylemeye çalıştığım şey, sonraki tablo anahtarı yerine, derleyici tüm gerçek işleri sonraki tablo anahtarından ilkine taşıyabilir ve sonra tüm anahtar dallarının sonuna atlamak için ifeq kullanır. Bu yüzden burada gördüğüm olası bir cevap: ilk derleyici derleyicisinde, bilinen vaka sayısına dayanarak ifeq atlama için etiketin önceden işlemeye çalıştığı, ancak bunun tek neden olduğundan emin değilim. @ericbn önerildiği gibi
Update2
, ben int ve derleyici bana düz lookupswitch verdi i ile
switch (i) {
case 97: return -100;
case 51713: return 1;
case 99: return 2;
default: return -1;
}
derlemeye çalıştık.
Farklı String (lar) nedeniyle pigeonhole prensibi aynı hashCode sahip olabilir. Sanırım bu yüzden iki anahtar (lar) var. –
Sadece bir anahtar olduğunu düşünmüyor musunuz? ikinci anahtar koşullu dönüş içindir. – HuStmpHrrr
@HuStmpHrrr İkinci anahtar, görünüşte beklenmedik bir dolaylı katma katmanı sunar; tablodan bakılan atlar, "goto" hedefleri olarak ilk anahtar bloğuna direk olarak yerleştirilmiş olabilir. –