2015-04-26 8 views
5

Ecco un frammento di codicePerché in JVM Integer è memorizzato come byte e breve?

public class Classifier { 
    public static void main(String[] args) 
    { 
     Integer x = -127;//this uses bipush 
     Integer y = 127;//this use bipush 
     Integer z= -129;//this use sipush 
     Integer p=32767;//maximum range of short still sipush 
     Integer a = 128; // use sipush 
     Integer b = 129786;// invokes virtual method to get Integer class 

    } 

} 

Ecco byte di codice parziale di questo

 stack=1, locals=7, args_size=1 
     0: bipush  -127 
     2: invokestatic #16     // Method java/lang/Integer.valueO 
f:(I)Ljava/lang/Integer; 
     5: astore_1 
     6: bipush  127 
     8: invokestatic #16     // Method java/lang/Integer.valueO 
f:(I)Ljava/lang/Integer; 
     11: astore_2 
     12: sipush  -129 
     15: invokestatic #16     // Method java/lang/Integer.valueO 
f:(I)Ljava/lang/Integer; 
     18: astore_3 
     19: sipush  32767 
     22: invokestatic #16     // Method java/lang/Integer.valueO 
f:(I)Ljava/lang/Integer; 
     25: astore  4 
     27: sipush  128 
     30: invokestatic #16     // Method java/lang/Integer.valueO 
f:(I)Ljava/lang/Integer; 
     33: astore  5 
     35: ldc   #22     // int 129786 
     37: invokestatic #16     // Method java/lang/Integer.valueO 
f:(I)Ljava/lang/Integer; 
     40: astore  6 
     42: return 

quanto vedo per gamma integer tra -128 to 127 utilizza bipush che spingono un byte nello stack come numero intero valore. in un intervallo -32768 to 32767 utilizza short come classe wrapper come sipush. Per il prossimo utilizza Integer. Cosa JVM usa byte e short per memorizzare il valore Integer?

+0

Non è questo un duplicato di https://stackoverflow.com/questions/ 20897020/why-integer-class-caching-values-in-the-range-128-to-127? –

+0

@dystroy la mia unica domanda rimane ancora senza risposta perché byte e short per int? –

+1

Se hai due domande separate, è davvero meglio fare due domande separate. Molte persone potrebbero conoscere la risposta all'una ma non all'altra; dovrebbero dare risposte o no? E come sceglierai quale risposta accettare? Si prega di non combinare due domande in una pubblicazione. –

risposta

2

quanto riguarda la mia ho capito.

Come potete rimanga istruzioni bytecode non memorizza int come byte o short Primo perché bipush o short: bipush ha 2 byte uno per codice operativo e il secondo per il valore. Ciò che può variare tra -128 tp 127 (cioè 2 potenza 8) Si risparmia spazio e tempo di esecuzione. Come si può vedere da remianing codice compilatore non crea un riferimento di tale variabile come intero tipo

2: invokestatic #16     // Method java/lang/Integer.valueO 
f:(I)Ljava/lang/Integer; 

e poi astore_1 che store what's on top of the stack i.e a reference here into local variable 1 Simile è per sipush in cui è possibile memorizzare il valore della gamma (-32768 to 32767) Allucinante è 3 byte di set di istruzioni, un byte per opcode e restano due byte per valore (i.e può contenere 2 potenza 16)

Ora perché no lDC JVM ha un pool costante per tipo. Il codice byte richiede dati, ma il più delle volte è questi dati sono troppo grandi per essere memorizzati direttamente nei codici byte. quindi è memorizzato nel pool costante e il codice byte contiene un riferimento al pool costante. Nei ldc fa spingere un INDEX costante da un pool costante (String, int o float) nello stack che consuma tempo supplementare e cicli Ecco un confronto tra ruvida ldc funzionamento e bipush funzionamento

enter image description hereenter image description here

JVM Bytecode ref qui si dice

Ove possibile, la sua più efficiente di utilizzare uno dei bipush, sipush, o uno dei le istruzioni const invece di ldc.

5

Non viene memorizzato come byte o short in fase di esecuzione, solo in bytecode. Supponiamo che voglia memorizzare il valore 120 in Integer. Scrivi il compilatore, quindi analizzi il codice sorgente e sai che il valore costante 120 può essere contenuto in un byte firmato. Perché non vuoi sprecare spazio nel tuo bytecode per memorizzare il valore 120 come valore a 32 bit (4 byte) se può essere memorizzato in 8 bit (1 byte), creerai un'istruzione speciale, che sarà in grado di caricare solo una byte dal metodo bytecode e memorizzarlo nello stack come 32 bit integer. Ciò significa che in fase di esecuzione hai davvero il tipo di dati integer.

Il codice risultante è più piccolo e più veloce rispetto all'utilizzo di ldc ovunque, che richiede una maggiore interazione con jvm a causa della manipolazione con il pool costante di runtime.

bipush ha 2 byte, un byte opcode, secondo byte immediato valore di rilevamento. Perché hai solo un byte per il valore, può essere utilizzato per valori compresi tra -128 e 127.

sipush ha 3 byte, un opcode byte, secondo e terzo byte immediato valore costante.

formato bipush:

bipush 
byte 

formato sipush:

sipush 
byte1 
byte2 
0

Uno dei motivi potrebbe essere il vantaggio relativo al codice byte che è stato menzionato in altre risposte.

Tuttavia, si potrebbe anche ragionare a tale proposito iniziando dalla lingua . In particolare, non si desidera inserire un cast quando il valore (costante) è effettivamente rappresentabile nel tipo di destinazione.

Quindi, un motivo per il comportamento osservato è: Il compilatore utilizza il tipo più piccolo possibile che può rappresentare il valore costante specificato.

Per l'assegnazione a int (o Integer) non sarebbe necessario, ma non fa alcun danno quando il bytecode assegna un tipo "più piccolo" a un tipo "più grande". Per i tipi più piccoli, invece, è necessario per utilizzare il tipo più piccolo, quindi l'utilizzo del "bytecode per il tipo più piccolo" è il comportamento predefinito.


questo è anche implicitamente indicato come "a tempo di compilazione restringimento delle espressioni costanti" in Section 5.2., Assignment Contexts del linguaggio Java Specification:

un restringimento di conversione primitivo può essere utilizzato se il tipo di variabile è byte, short o char e il valore dell'espressione costante è rappresentabile nel tipo della variabile.

...

Il restringimento in fase di compilazione delle espressioni costanti significa che il codice come ad esempio:

byte theAnswer = 42; 

è permesso. Senza il restringimento, il fatto che l'intero letterale 42 ha Tipo int vorrebbe dire che un cast al byte sarebbe necessario:

byte theAnswer = (byte)42; // cast is permitted but not required 
Problemi correlati