I sottocontesti in Java sono righe separate nello stack?
Domanda
In Java questo è il caso:
public void method() {
if (condition) {
Object x = ....;
}
System.out.println(x); // Error: x unavailable
}
Quello che mi chiedo è questo:È il fatto che x
è limitato all'ambito del if
-statement è solo una funzionalità del compilatore Java, o lo è x
effettivamente rimosso dallo stack dopo il if
-dichiarazione?
Soluzione
No, blocchi di codice non si ottiene uno stack frame separato, l'uso quella del metodo circostante.
Tuttavia, una volta portata foglie variabile, esso è posto nella stack frame corrente può essere riutilizzato per altre variabili.
La struttura e l'uso di uno stack frame è descritta nella Java Virtual Machine Specification § 3.6 Frames :
Un nuovo telaio viene creata ogni volta che un metodo viene richiamato. Un frame viene distrutta quando i suoi Completa metodo di chiamata, se tale termine è normale o brusca (si getta un'eccezione non rilevata).
Questa specifica sicuramente un 1:. Relazione tra 1 chiamate di metodo e cornici
Altri suggerimenti
I blocchi fanno parte del linguaggio Java (che è a linguaggio di programmazione strutturato) mentre non fanno parte del bytecode compilato (che è un non strutturato lingua).
Una specifica del metodo in un file di classe specifica quante variabili locali il metodo utilizza in totale, sopra l'effettivo elenco di istruzioni.Ma dove i blocchi una volta si trovavano nel codice Java non possono essere dedotti dal bytecode.
Prima di tutto, nelle variabili bytecode vengono memorizzati nelle fessure variabili e slot di variabili e non in pila. Lo slot potrebbe essere riutilizzato da un'altra variabile, ma non è garantito che il valore sarebbe stato rimosso dalla fessura variabile.
Ad esempio, la seguente classe
public class A {
public void method(boolean condition) {
6 if (condition) {
7 Object x = "";
8 System.out.println(x);
9 }
10 System.out.println(condition);
}
}
viene compilato in bytecode questo:
// class version 50.0 (50)
public class A {
...
// access flags 0x1
public method(Z)V
L0
LINENUMBER 6 L0
ILOAD 1
IFEQ L1
L2
LINENUMBER 7 L2
LDC ""
ASTORE 2
L3
LINENUMBER 8 L3
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 2
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
L1
LINENUMBER 10 L1
FRAME SAME
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ILOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (Z)V
L4
LINENUMBER 11 L4
RETURN
L5
LOCALVARIABLE this LA; L0 L5 0
LOCALVARIABLE condition Z L0 L5 1
LOCALVARIABLE x Ljava/lang/Object; L3 L1 2
MAXSTACK = 2
MAXLOCALS = 3
}
Si noti che variabile X creato alla riga 7 è memorizzato nella fessura variabile 2, che è ancora disponibile presso il bytecode corrispondente alla linea 10.
Non v'è alcuna specifica su come linguaggio Java deve essere compilato in bytecode altri poi alcuni esempi come compilare correttamente alcuni costrutti del linguaggio. Tuttavia compilatore Java è permesso di eliminare le variabili non utilizzate. Per esempio. se x sono stati assegnati, ma non utilizzati ovunque, compilatore è permesso di abbandonare quel codice. Allo stesso modo, il compilatore è messa in linea tutte le costanti statiche.
Sì, è davvero rimossa dalla pila rendendo slot precedentemente occupato da 'x' riutilizzabile da un altro variabile locale.