Check out the new USENIX Web site. next up previous
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 $ C$ is loaded by the class loader. Loading interfaces is handled similarly.

  1. Loading superclasses. Recursively load all the superclasses of $ C$, if they are not loaded already.

  2. Check for constraints related to the class hierarchy. In this step we only need to check things related to class $ C$. Refer to Section 4.4.1 for details.

  3. Create a global allocation table entry for class $ C$ ($ T_c$). This $ T_c$ 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 $ C$'s superclasses.
    In order to do this, we have to check the global allocation table entries of all the superclasses of $ C$ (recursively, they are already consistent with each other). Note that this data is not copied from the global allocation table entries of $ C$'s superclasses to the entry of $ C$, 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 $ C$'s fresh instance members (those members defined in $ C$ but not in any superclasses of $ C$). Here we can only use those offsets which are not yet used in any superclasses of $ C$. In particular some offsets (e.g. 0) are reserved for incompatible change exception handling and cannot be used to map members to.

  4. Create the class data structures (e.g. vtable) of class $ C$. We do this according to the layout specified in the global allocation table entry $ C$ and the entries of $ C$'s superclasses. If the global allocation table maps a member to position $ k$, then the data for the actual member is put at position $ k$ 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.

  5. Fill in currently loaded classes' offset table entries that correspond to the members in $ C$. We do this with the help of the global allocation table entries of $ C$ 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 $ C$, 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.

  6. Fill in the offset table of class $ C$. This is done in the same manner as the last step. For $ C$'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.

  7. Add the information of class $ C$ to the loaded class cache. Also add the class hierarchy constraints demanded by class $ C$ to the set of constraints maintained by the system.

  8. Extend the ctable list with a pointer to the ctable of class $ C$.


next up previous
Next: Implementation and Performance Evaluation Up: Algorithm Previous: Compiler
Dachuan Yu 2002-05-23