Hello I am here again. For completeness I will post this. Though some part may be repeated.
I am going to assume without the need of any example the following three points
1) Objects are created in the heap
2) Member static variables are created in the type data for the class in which they were declared.
3) Member instance variables are created in the image of the object to which they are associated.
a) For members of a class:
a1) Variables of literals
Variables (static or instance) spawn a CONSTANT_Fieldref in the constant pool of the class in whichwere declared. There are, as well, entries of the proper type for containing the values as follows:
boolean, byte, short, char, int...........CONSTANT_Integer_Info double....................................CONSTANT_Double_Info float.....................................CONSTANT_Float_Info long......................................CONSTANT_Lonf_Info String....................................CONSTANT_String_Info
But this entries are not created if the value of variable can be assigned with one of the following bytecodes:
bipush, sipush, iconst_(0,1,2,3,4,5,m1), dconst_(0,1), fconst_(0,1,2) y lconst_(0,1)
Other classes that use these variables have in the constant pool CONSTANT_Fieldref entries that would be resolved at run time. They will be translated to pointers to the variable in the type data if the variable is static. They will be translated to offsets to the instance data in the image of the object, if the variables are not static.
There is an article (though in Spanish) with examples and the output of a class file parser and javap at
http://usuarios.tripod.es/JoseBotella/ConstantPool/ConstantPool.html a2) Final statics of literals
They always spawn an entry of the "proper" type in the contant pool for containing the value, regardless the value itself. That is, no bytecode from the previously shown list is used in this case.
The classes that acces these filelds contain in their constant pool entries of the "poper" type only in no bytecode of the previous list can be used.
a3) Final instances of literals
They work the same as the previous one, except that they also generate CONSTANT_Fieldref entries in the class that declared them.
a4) Reference fields
The class that declares reference fields contains CONTANT_Field entries for each of them.
The reference for a variable or final instance is stored in the object itself via a putfiield bytecode.
The reference for a variable or final static is stored in the type data via a putstatic bytecode.
For instance:
class Dummy {}public class MemberReferences {
Dummy d1 = new Dummy();
static Dummy d2 = new Dummy();
final Dummy d3 = new Dummy();
final static Dummy d4 = new Dummy();
}
class Dummy {}
produces the javap output:
Method MemberReferences()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 aload_0
5 new #2 <Class Dummy>
8 dup
9 invokespecial #3 <Method Dummy()>
12 putfield #4 <Field Dummy d1>
15 aload_0
16 new #2 <Class Dummy>
19 dup
20 invokespecial #3 <Method Dummy()>
23 putfield #5 <Field Dummy d3>
26 return
Method static {}
0 new #2 <Class Dummy>
3 dup
4 invokespecial #3 <Method Dummy()>
7 putstatic #6 <Field Dummy d2>
10 new #2 <Class Dummy>
13 dup
14 invokespecial #3 <Method Dummy()>
17 putstatic #7 <Field Dummy d4>
20 return
where putstatic and putfield can be seen in action.
a5) Primitive members unknown at compile time
They are quite similar to reference fields. They generate CONSTANT_Fieldref entries.
The primitives that are instances are stored with the object via a putfield bytecode.
The primitives that are static are stored in the type data via a putstatic bytecode.
For instance:
public class PrimitiveMembersAtRunTime {
double d1 = Math.random();
final double d2 = Math.random();
static double d3 = Math.random();
final static double d4 = Math.random();
}
produces the javap output:
Method PrimitiveMembersAtRunTime()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 aload_0
5 invokestatic #2 <Method double random()>
8 putfield #3 <Field double d1>
11 aload_0
12 invokestatic #2 <Method double random()>
15 putfield #4 <Field double d2>
18 return
Method static {}
0 invokestatic #2 <Method double random()>
3 putstatic #5 <Field double d3>
6 invokestatic #2 <Method double random()>
9 putstatic #6 <Field double d4>
12 return
Phew, that was for the fields of a class now:
b) For the local variables:
Only the final primitives with a value known at compile time ARE NOT stored in the local variable section of the stack frame for the method that declared them.
b1) Local references
They are always stored in the local section variable via a astore bytecode
For instance:
public class LocalFields {
public static void main(String[] args) {
Dummy d1 = new Dummy();
final Dummy d2 = new Dummy();
}
}
class Dummy {}
/*
Method void main(java.lang.String[])
0 new #2 <Class Dummy>
3 dup
4 invokespecial #3 <Method Dummy()>
7 astore_1 //save d1 in the local variable 1
8 new #2 <Class Dummy>
11 dup
12 invokespecial #3 <Method Dummy()>
15 astore_2 //save d2 in the local variable 2
16 return
b2) Local primitives
public class LocalPrimitives {
public static void main(String[] args) {
double d1 = 1.0;
double d2 = 2.0;
final double d3 = 1.0;
final double d4 = 2.0;
final double d5 = 3.0;
System.out.println(d3);
System.out.println(d4);
System.out.println(d5);
///////////////////
int i1 = 1;
int i2 = 32768;
final int i3 = 2;
final int i4 = 32769;
final int i5 = 3;
System.out.println(i2);
System.out.println(i3);
System.out.println(i4);
///////////////////
double runTime1 = Math.random();
final double runTime2 = Math.random();
}
}
/*
Inside a method only the final primitive with a value known at compile time ARE NOT saved in the local variable section.
The compiler makes some optimizations:
It does not repeat local variables or constant pool entries with the same value, but it reutilize them
The local final variables are not saved in the local variable section. Only if they are used a bytecode, able to represent the value, or otherwise an entry in the constant pool push the value in the operand stack.
Method void main(java.lang.String[])
0 dconst_1
1 dstore_1 //save d1
2 ldc2_w #2 <Double 2.0>
5 dstore_3 //save d2
6 getstatic #4 <Field java.io.PrintStream out>
9 dconst_1
10 invokevirtual #5 <Method void println(double)>
13 getstatic #4 <Field java.io.PrintStream out>
16 ldc2_w #2 <Double 2.0>
19 invokevirtual #5 <Method void println(double)>
22 getstatic #4 <Field java.io.PrintStream out>
25 ldc2_w #6 <Double 3.0>
28 invokevirtual #5 <Method void println(double)>
///////////////////////
31 iconst_1
32 istore 11 //save i1
34 ldc #8 <Integer 32768>
36 istore 12 //save i2
38 getstatic #4 <Field java.io.PrintStream out>
41 iload 12
43 invokevirtual #9 <Method void println(int)>
46 getstatic #4 <Field java.io.PrintStream out>
49 iconst_2
50 invokevirtual #9 <Method void println(int)>
53 getstatic #4 <Field java.io.PrintStream out>
56 ldc #10 <Integer 32769>
58 invokevirtual #9 <Method void println(int)>
///////////////////////////
61 invokestatic #11 <Method double random()>
64 dstore 16 //save runTime1
66 invokestatic #11 <Method double random()>
69 dstore 18 //save runTime2
71 return
*/
Did I forget something? Is there something wrong?