Sont en Java séparent les sous-contextes des lignes sur la pile?
Question
En Java c'est le cas:
public void method() {
if (condition) {
Object x = ....;
}
System.out.println(x); // Error: x unavailable
}
Ce que je me demande est la suivante: Est-ce le fait que x
est limitée à la portée de la if
-déclaration juste une caractéristique du compilateur Java, ou est x
effectivement retiré de la pile après la if
-instruction ? p>
La solution
Non, les blocs de code ne reçoivent pas un cadre de pile séparée, l'utilisation d'une de la méthode environnante.
Cependant, une fois la portée des feuilles de variables, il sa place dans le cadre de la pile actuelle peut être réutilisée pour d'autres variables.
La structure et l'utilisation d'un cadre de pile est décrite dans le Java Virtual machine Spécification § 3.6 Cadres de:
Une nouvelle trame est créée chaque fois qu'une méthode est appelée. Une trame est détruite lors de ses achève d'invocation de méthode, si cette réalisation est normal ou brusque (il déclenche une exception non traitée).
Ceci indique certainement un 1: 1. Relation entre les invocations de méthodes et cadres
Autres conseils
Les blocs font partie du langage Java (qui est un langage de programmation structuré ) alors qu'ils ne font pas partie du bytecode compilé (qui est un non structuré langue ).
Une spécification de méthode dans un fichier spécifie classe nombre de variables locales les utilisations de la méthode au total, au-dessus de la liste réelle des instructions. Mais où les blocs une fois où dans le code Java ne peuvent pas être déduites du bytecode.
Tout d'abord, dans les variables de bytecode sont stockés dans les emplacements variables et des fentes variables et non pas sur la pile. La fente peut être réutilisé par une autre variable, mais il est pas garanti que la valeur serait retirée de la fente variable.
Par exemple, la classe suivante
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);
}
}
est compilé dans ce bytecode:
// 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
}
Notez que la variable x créée à la ligne 7 est stockée dans l'emplacement de la variable 2, qui est encore disponible pour le pseudo-code correspondant à la ligne 10.
Il n'y a aucune spécification sur la façon dont le langage Java doivent être compilés dans le bytecode autres que quelques exemples comment compiler correctement certaines constructions linguistiques. Cependant compilateur Java est autorisé à éliminer les variables inutilisées. Par exemple. si x ont été attribués, mais pas utilisé partout, le compilateur est autorisé à déposer ce code. De même, le compilateur est inline toutes les constantes statiques.
Oui, il est vraiment retiré de la pile faisant la fente précédemment occupé par « x » réutilisable par une autre variable locale.