Each class needs a type descriptor in the constant block of this class (see Linker32). This type descriptor will be needed to find instance methods or to do type checking. All arrays - even arrays with elements being of an interface type - need a type descriptor. Interfaces themselves need no type descriptor because there cannot be instances of interfaces.
However, there is one exeption to this. If an object, which is of type “array of interface type”, is checked with instructions like instanceof or checkcast, then the type descriptor of the array must have an entry componentTD (see below). And this entry must be a type descriptor of an interface. For such cases even an interface needs a type descriptor. This type descriptor can be very small and most entries may be ommitted. When parsing the classes, affected interfaces are inserted in a special list.
The fields size indicates the size (in bytes) of an object of this type (without tag, see Objects). For arrays the entry is arrayComponentSize, which is the size (in bytes) of one array element. The name of the class could be used for reflection.
The entry extensionLevel gives the number of superclasses. The method table is discussed below. The type table (baseClassTD up to baseClassTD[extLevel]) and interface type table (interface ChkId1, …) is used for Type Checking. The interface method table together with the interfaceDelegateMethod and the entries with interface0Id, interface0MethodOffset serves to find the right interface method, see Interfaces.
The garbage collector has to know which instance fields are references. For this there is a field instPtrOffset. This field has a fixed offset within the type descriptor. From there you can reach a list with all reference fields (nofInstPtr, instPtrOffset, … ).
Type descriptors for arrays are solely used for type checking. They contain the references to all type descritors of the lower dimensional arrays of the same base type. If necessary, these lower dimensional types must be created by the class file reader. The field arrayDimension gives the number of dimension of this array. The bit P (primitive) indicates whether this is an array of base types, such as byte, short, … (P = 1) or if its an array of regular classes (P = 0). For arrays of base types the value of componentTD is set to 0. The P-bit is also set in the higher dimensional type descriptors, e.g. in [S, [[S and [[[S.
The reduced type descriptor for interfaces comprises the fields from size to intfTypeChkOffset and the interface table. The type table with the base classes can be omitted. Important: the table with the interface id's must include the own id!
The method table within the type descriptor contains the addresses of all instance methods of this class starting with the methods of the superclass (if present). The compiler translates the instruction invokevirtual into:
For this to work, it is important, that methods which are overridden, are placed exactly at the same offset in the table as their overriding method.
For all examples below test cases have been created for the compiler.
The structure of the type descriptor is shown. The order of methods of a class must be maintained in all its subclasses! Standard order is: first constructors then normal methods.
This example extends example A and shows what happens, if a method with identical signature is present in several interfaces.