We provide here a rough view of how class descriptions and objects
are maintained in the JVM.
Object oriented processing involves a considerable amount of bookkeeping.
The class definitions with their fields and methods must be stored
and accessed when needed. The data for the instances of these classes
must be stored and then the memory released when the objects are
no longer needed. Dynamic linking means that initial references
in the class files are symbolic (that is, simple strings for class
names and for the field and method descriptors). So the JVM must
replace these with actual memory reference values when it loads
a class and links it to the other classes referenced by the fields
and methods.
We discussed in Chapter 1: Supplements
: JVM the organization of the JVM and its processing. Here we
give a cartoon version with pseudo-code to illustrate the basic
concepts involved.
Let's use the MyBoolean example in the Chapter
3: Supplements : Class Types. When the class is loaded into
the JVM, the class definition occupies part of the memory allocated
for the JVM's runtime data area. This is the section of the
JVM's storage area where it manages the class definitions, objects,
and other items needing memory.
Note: The JVM specification allows for a lot of flexibility
in how an implementation organizes memory but what is described
here should be general to most implementations. (See Chapter 5
in ref. Venners).
In the figure below we show an arrangement that a JVM might use
to organize its data area. (In practical terms, this might be a
set of arrays.) The class definition elements fill a section of
one array, while object data fills a second array, and static data
fills a third array.
We show the class MyBoolean after it has been loaded into
the JVM. It includes the Constant Pool section of the class
that holds various strings (such as names of methods and fields),
constants (such as values from literals), references to other classes,
and additional bookkeeping information. The symbolic references
must be resolved to actual memory pointers as they are needed.
After the constant pool comes the section describing the fields
and methods. The methods section holds the actual bytecode instructions
for each method.
JVM
Runtime Data Area
Method
Area |
.... |
MyBoolean Class
-----------
Constants Pool
strings
references to
other classes
etc
-----------
Fields
i
----------
Constructors
MyBoolean(int j)
----------
Methods
set(int j) bytecode
isTrue() bytecode
AND bytecode
OR bytecode
|
.... |
... Other
classes ... |
.... |
|
Heap |
.... |
... MyBoolean object
... |
.... |
.... |
...
Java
Stack |
.... |
... stack frames
during
method execution... |
.... |
.... |
...
PC Registers |
.... |
... Each thread
assigned a Program Counter register ... |
.... |
.... |
...
Native
Method Stacks |
.... |
... stack frames
used for invoking native methods ... |
.... |
.... |
|
|
The runtime data area is the working memory buffer used by the
JVM to store the class definitions, object data, method frame
stacks, etc. We show symbolically how arrays could hold such data.
(Ref. Venners)
For example, when a new object is created, the instance data will
be inserted into the data array. Then when a particular object
is needed, as with a method invocation on the object, the instance
variables for the class and the local data for the method will
be loaded.
Suppose that a method in a separate class holds the following code
:
...
MyBoolean bool0 = new MyBoolean(MyBoolean.True);
MyBoolean bool1 = new MyBoolean(MyBoolean.False);
MyBoolean bool2 = new MyBoolean(MyBoolean.True);
...
The JVM would then create three instances of MyBoolean, which in effect
means storing the instance data (the "int i" field in MyBoolean)
for each of the three objects in the data array.
The JVM will maintain an internal list of pointers to the locations
of the class definitions and their objects. So, for example, when
a method currently being executed by the JVM references a field
in another object or invokes a method of another object of a different
class, the JVM will know where in the above arrays to find the field
values and methods.
Say that the method above later invokes a method for the bool0
object, as in
...
if( bool0.AND(bool1) ) x = 5;
...
The JVM would load the AND method on top of its stack of methods
and set the i variable to the entry in the data
array for bool0. It also passes the reference
to bool1
in the argument to the AND method. The JVM would then
execute each instruction in the AND method until it finished
and then unload that method from its stack and return to executing
the method that invoked AND.
So we see that our conceptual image of objects as independent,
self-contained objects is not exactly how they are in reality. The
machinery of the object (that is, the class definition) resides
in a single location. The objects consist of the particular values
of the instance and static field values that are stored in a separate
location. When a particular object executes a method, its data is
referenced by the variables in the bytecode machinery. When another
object executes that method, all the necessary bytecode pointers
switch to that data.
Metaphorically, the gun is the method bytecode and the bullets
are the data that comprise a particular object!
Additional description of the JVM is available in the links below.
References & Web Resources
Latest update: Oct. 5, 2005
|