Next: Implementation and Performance Evaluation
Up: Algorithm
Previous: Compiler
Class Loader
The class loader needs to maintain the related data structures
such as the global allocation table, offset tables, and metadata
structures like the vtable.
It also has to check for various constraints during class loading.
Here is what happens when a class is loaded by the class loader.
Loading interfaces is handled similarly.
- Loading superclasses.
Recursively load all the superclasses
of , if they are not loaded already.
- Check for constraints related to the class hierarchy.
In this step we only need to check things related to class .
Refer to Section 4.4.1 for details.
- Create a global allocation table entry for class ().
This maps every member
to its position information in the corresponding metadata structure
(e.g. vtable), together with the modifier tags.
Static members are easy to deal with,
but special attention must be paid when mapping instance members,
because we have to do it in such a way that it is consistent with the
global allocation table entries of 's superclasses.
In order to do this,
we have to check the global allocation table entries of all the
superclasses of (recursively, they are already consistent with
each other). Note that this data is not copied from the global
allocation table entries of 's
superclasses to the entry of , because that would be space-inefficient.
This is also when we make sure final methods are not overridden.
After that, we construct the mappings of 's fresh instance
members (those members defined in but not in any superclasses
of ).
Here we can only use those
offsets which are not yet used in any superclasses of .
In particular some offsets (e.g. 0) are reserved
for incompatible change exception handling and cannot be used to map
members to.
- Create the class data structures (e.g. vtable) of class .
We do this according to the
layout specified in the global allocation table entry and the
entries of 's superclasses. If the global allocation table maps
a member to position , then the data for the actual member is put at
position of the corresponding data structure.
Beside those specified by the global allocation table, we also need to
fill in the reserved entries with pointers to particular exception code.
- Fill in currently loaded classes' offset table entries that
correspond to the members in .
We do this with the help of the global
allocation table entries of and its superclasses. This step is
done by iterating over the ctable list.
An inverse ctable
list would probably help to improve efficiency.
Here we may find out that other classes might be expecting a
non-existent member from , or the expected access is not granted
by comparing the modifier tags. In these
cases we put offsets of exception code (e.g. 0) in the offset tables
of those classes. However, as we discussed in Section 4.2,
removed fields cannot be handled in the same
manner. We raise an
exception immediately when trying to fill in the offset table entry for that
removed field.
- Fill in the offset table of class .
This is done in the same manner as the last step.
For 's offset table, we fill in those entries
that correspond to members expected from the loaded classes.
The entries for members expected from
not-yet-loaded classes are left to be filled in later.
- Add the information of class to the loaded class cache.
Also add the class hierarchy constraints demanded by class to
the set of constraints maintained by the system.
- Extend the ctable list with a pointer to the ctable of
class .
Next: Implementation and Performance Evaluation
Up: Algorithm
Previous: Compiler
Dachuan Yu
2002-05-23