4. Class Loading

Class Loading & Constant Pool Resolution

midjvm-internalsclass-loading

A compiled .class file's constant pool is a flat, 1-indexed table every other part of the classfile refers to by index instead of storing values inline -- string literals, class names, and method/ field signatures all get deduplicated into one pool. A Methodref entry (what a method-call instruction like invokevirtual actually points at) doesn't contain a class name or method name directly -- just two indices: one pointing at a Class entry, one at a NameAndType entry, each of which points at further Utf8 entries. Resolving a symbolic reference means walking that whole chain.

Implement:

  • get_utf8(index) -- return the string value of the Utf8 entry at index; raise ValueError if that entry isn't a Utf8 entry.
  • resolve_class(index) -- return the binary class name a Class entry names (its name_index, looked up via get_utf8).
  • resolve_name_and_type(index) -- return (name, descriptor) for a NameAndType entry (both looked up via get_utf8).
  • resolve_methodref(index) / resolve_fieldref(index) -- return {"class": ..., "name": ..., "descriptor": ...} by resolving a Methodref/Fieldref entry's class_index (via resolve_class) and name_and_type_index (via resolve_name_and_type).

Every resolver should reject an index whose entry has the wrong tag (e.g. calling resolve_methodref on a Fieldref index) by raising ValueError -- a classfile parser has to validate this, not assume the bytecode is well-formed.

Example

pool = ConstantPool([
    None,
    ("Utf8", "Calculator"),
    ("Class", 1),
    ("Utf8", "add"),
    ("Utf8", "(II)I"),
    ("NameAndType", 3, 4),
    ("Methodref", 2, 5),
])
pool.resolve_methodref(6)
# -> {"class": "Calculator", "name": "add", "descriptor": "(II)I"}

Constraints

  • Index 0 is always invalid (the constant pool is 1-indexed).
  • An out-of-range index, or an index whose entry has the wrong tag for the resolver called, must raise ValueError rather than returning something silently wrong.

Real-world grounding

  • HotSpot's classfile parser (where the raw constant pool bytes get parsed into typed entries and every cross-reference's tag gets validated -- exactly the checks this exercise's ValueErrors model): src/hotspot/share/classfile/classFileParser.cpp
  • HotSpot's runtime constant pool representation and its own resolve_* family of methods (klass_ref_at, name_ref_at, signature_ref_at, ...) that this exercise's resolve_methodref/ resolve_fieldref mirror in spirit: src/hotspot/share/oops/constantPool.cpp

Real classfiles have a dozen more constant pool tag kinds (Integer, Float, Long, Double, String, InterfaceMethodref, MethodHandle, MethodType, InvokeDynamic, ...) and HotSpot defers full resolution of some entries until first use ("lazy" resolution) rather than doing it all at parse time -- this exercise implements the core chained-index lookup underneath every variant.

hints
constant_pool.pysign in to run
Loading...
test result

This is a preview. Sign in to run this exercise against the real tests.