2015-06-09 13 views
5

Podczas odczytywania specyfikacji JVM (tak jak robię), byłem bardzo zaskoczony, gdy natknąłem się na kody kreskowe 7 iconst_<i>. W końcu jest tylko jeden bajt do zabawy.Dlaczego JVM ma ikony opcodes iconst_2 - iconst_5?

Bardzo rzadko zapisuję literały dla 2, 3, 4 lub 5 w moim kodzie. Rozumiem, dlaczego -1, 0 i 1 mogą być traktowane specjalnie, ale wydaje mi się niesamowite, że projektanci będą chcieli wysadzić 4 cenne opkody na numery, które akurat są niewielkie.

Czy ktoś wie, czy istnieje ku temu uzasadniony powód? Czy nie doceniam korzyści z nich płynących?

+0

Istnieje 255 kody op dostępne. Podczas projektowania zestawu instrukcji VM bardzo trudno jest go używać w pobliżu każdego z nich. Oczywiście Jim Gosling uważał, że to dobry dea, i to bezkosztowe, dopóki się nie skończy, jak rozdawanie darmowych biletów do teatru, więc czemu nie? – EJP

Odpowiedz

4

Myślę, że twoje założenie jest poprawne: tylko po to, by kod bajtowy był mniejszy, a interpreter Javy był odrobinę szybszy (w tamtych czasach nie było kompilatora JIT). Zauważ, że te bajty mogą być używane znacznie częściej niż się spodziewasz. Rozważmy na przykład następujący kod:

int[] a = {10, 20, 30, 40}; 

Skutecznie to skompilowany do czegoś podobnego:

int[] a = new int[4]; 
a[0] = 10; 
a[1] = 20; 
a[2] = 30; 
a[3] = 40; 

więc o iconst_0 do iconst_4 są stosowane, nawet jeśli nie mają takich stałe w kodzie źródłowym.

+0

Dobra uwaga, dzięki. – user1675642

3

Nadzieja może wyrobić sobie pytanie, dlaczego marnować 4 kod operacji ..

zobaczyć kod bajtowy kod

public static void main(String[] args) { 
     int b = 20; 
     int c = 5; 
     int d= 6; 
    } 

część kodu Byte

0: bipush  20 
2: istore_1 
3: iconst_5 
4: istore_2 
5: bipush  6 
7: istore_3 

Jak widać dla liczby większej 5 zaczyna używać bipush, które są zwykle mniej wydajne niż odpowiednik iconst_<n> i zajmują więcej bajtów w pliku klasy.

bipush byte1 rozszerza byte1 do int i następnie wypycha ją na stosie, ponieważ każde gniazdo na stosie Java wynosi 32 bitów szerokości (JVM jest stos based Virtual Machines)

i zobaczyć, jeśli bipush zajmuje więcej bajt ..

zobaczyć rozmiar pliku klasy z dwóch następującego kodu. (ten rozmiar to na moim komputerze 64-bitowym .. może się różnić na komputerze, ale różnica będzie sam e)

public class Test2 { 

    public static void main(String[] args) { 
     int b = 5; 

    } 

} 

rozmiar 406 bajtów

teraz jeśli mogę wymienić b =6; rozmiar tego samego pliku klasy staje się 407 bytes, który pozostaje niezmienny do nawet gdy b=127, który również używa bipush.Ta różnica w wielkości jest ze względu na fakt, że bipush ma 2 bajty, jeden bajt kod operacji, drugi bajt natychmiastową wartość constat

Format bipush:

bipush 
byte 

jak widać z linii 5: bipush 6 w kodu bajtowego podczas gdy iconst_<n> używa tylko 1 bajtu.

Więc takie bytecodes są zdefiniowane dla niektórych powszechnie pchane numerów, aby zwiększenia efektywności wykonywania kodu bajtowego i zmniejszyć rozmiar strumieni kodu bajtowego.

i jak Tagir powiedział te liczby byłyby wykorzystywane częściej niż można by pomyśleć