====== Class File Reader ====== ===== Course of Action ===== ==== Build ==== System classes as indicated by the configuration are loaded first. After this the root classes are loaded. For each class all other classes which are referenced in the constant pool and which have a class file (arrays may be referenced but have no class files) are kept in an import list and subsequently loaded. \\ System classes are classes like the kernel or heap. They must be loaded in any case. ==== Constant Pool ==== In the first run all entries are read. During the second run objects of type //item// are created if necessary and references are resolved. For every class, method or field an object is inserted in the object directory. In the third run the constant pool is reduced and includes now only references to the object directory.\\ [{{ .:classitems.png?550&direct | //Architecture of deep class file reader//}}] Each item has the fields //index//, //offset// and //address//. The meaning of this fields varies with the type of the item and is described in [[Fields of Item]]. Special consideration has to be paided for references to arrays. If an array is created as in ClassA[] obj = new ClassA[]; there will be a reference to //[LClassA;// in the constant pool and the class file reader creates an array descriptor object. However, there is no such reference for the following code Object obj = new ClassA[]; and in the Bytecode we only have //anewarray ClassA//. For this case we must make sure that an array descriptor is created as well. The same is true for arrays of base types.\\ For each class an array //interfaces// holds all interfaces which this class implements. In if this interfaces extend other interfaces, the superinterfaces are included in this array as well. ==== Bytecode Analysis ==== The Bytecode of all methods are analyzed and the attribute flags of all classes and methods are properly set. For this purpose each object of the object directory has a field //accAndPropFlags//. In the interface //org.deepjava.classItems.ICclassFileConsts// many flags are defined, such as byte apfPublic = 0, apfPrivate = 1, apfProtected = 2, apfStatic = 3, ... byte dpfBase = 15; dpfClassLoaded = dpfBase+0, dpfRootClass = dpfBase+1, ... For instance, each class will be marked if an instance of it is ever created or a class will be marked if one of its methods is ever called with //invokeinterface//. ==== Stubs ==== When reading the constant pool of a class many fields or methods of other classes are needed for whom entries in the object directory were not yet created. For these stubs are created. At the end all stubs have to be replaced by their real object. ==== Finish ==== At the end all stubs have to be replaced, miscellaneous class information is added, fields and methods are sorted. ===== Classes, Interfaces and Arrays ===== Generally all items are linked in lists (using the field //next//). All root classes are listed in a array //rootClasses// which is a static member of the class //org.deepjava.classItems.Class//. There are more lists (all static members in the same class), like: * //initClasses//: Regular classes and interfaces which have an initializer (a class constructor, see [[.:class_initialization|Initialization]]). This classes are linked with the field //nextClass//. * //nonInitClasses//: Regular classes without initialization. Linked with the field //nextClass//. * //arrayClasses//: Arrays, linked with the field //nextArray//. For type tests for higher dimensional arrays, the lower dimensional arrays must be present as well. As references to those serve the fields //nextHigherDim// and //nextLowerDim//. * typeChkInterfaces: See the comment below. There a a special case where an interface needs a type descriptor. This happens when type testing for an array of interfaces, see [[type_checking|Type Checking]]. Object o = new InterfaceA[10]; if (o instanceof InterfaceA[]) ... Such interfaces are listed and linked with the field //nextTypeChkInterface//. This field is not shown in the following overview. [{{ .:classlist.png?750&direct | //All classes, interfaces and arrays are linked in several lists//}}] Arrays have //java/lang/Object// as superclass, therefore their type descriptor must allow for calling its inherited methods. Further there are two arrays containing lists with regular classes and interfaces, respectively. Each list contains classes with the same extension level. The field //nextExtLevClass// is used for linking. In the figure above the links are not all shown for simplicity. \\ \\ ===== Fields ===== When parsing the constant pool all fields are denoted with the tag //Fieldref//. Each //Fieldref// entry has two further indices into the constant pool. These denote the class and an entry //NameAndType//, which again has to further indices with the name and the type. For each field a new object is added to the object directory. The class file reader adds all fields of a class in three linked lists: * Instance fields -> Class.instFields * Class fields -> Class.classFields * Constant fields -> Class.constFields (don't go into the target image!) The three lists are again linked among each other. The last entry of the //instFields// points to the first entry of //classFields// and the last entry of //classFields// points to the first entry of //constFields//. With this structure searching for a certain field object will be highly efficient. Additionally two references are kept, which point to the first instance or class field which is a reference. For this purposes all fields, which denote references, are entered at the end of the list. * First instance field which is a reference -> firstInstReference * First class field which is a reference -> firstClassReference The figure below shows an example for a class with two instance and two class fields as well as two constant fields. One of the instance fields is of a primitive type and one is a reference. Both class fields are of type reference. [{{ .:deep_classfilereader_fields.jpg?400&direct | Example of a class with six fields}}] \\ For efficiency reasons all fields of an object or a class (defined as //static//) with the same size in memory should be placed together, which is done by sorting. For this purpose there are three static arrays in //org.deepjava.classItems.Class//. When parsing the fields their size and type is determined and entered according to their size into the appropriate array. Finally, the arrays are read out in proper order and the objects are entered in the lists as shown in the previous figure. ===== Constants ===== When parsing the constant pool all constants can be found in there. According to their tag different objects are created for them. * Integer, Long, Float, Double: //new StdConstant//, the object contains the value of the constant, the name is "#" and the type is set accordingly. * String: //new StringLiteral//, the object stores the string, the name is "" and the type is //String//. When parsing the fields a check is made whether the attribute //ConstantValue// is set. This is the case for fields which are defined as //final//. If so, another object //ConstField// will be created which contains the name of the field, its type and a reference to an object //Constant//. \\ Let's take a look at an example: static final int a = 1; For the class field //a// an object of type //ConstField// with the name "a" will be created. At the same time an object with the value of 1 of type //StdConstant// will be created. This object has the name "#". \\ Important: The assignment of a value to a variable declared as //final// can be made when declaring it or in the constructor. This leads to the following cases. class ClassA { static final int a; static final int b = 2000000; static final String str1 = "test1"; static final String[] str2 = {"abc", "def"}; static final Object obj = new Object(); final int c = 3000000; final int d; static final double e = 0.1; static final double[] f = {0.5, 0,6}; ClassA() {d = 4000000;} static {a = 2000000;} } interface ITest3 { int x = 100; String str3 = "test3"; String[] str4 = {"a1", "a2"}; } * Case a: Attributes //static// and //final// are set. In the constant pool we have a=(class=ClassA, name="a", type='I'), it's not linked to a value. This only happens in ////. There, //a// is linked to the object of type //StdConstant// with a value of 1'000'000. In //field_info()// of //a// the attribute //ConstantValue// is not set, therefore the //dpfConst// flag won't be set either. //a// goes into the list //Class.classFields//. * Case b: Is not listed as field at all. Present as constant only in the constant pool. An object //NamedConst// is created which points to an object //StdConst// with a value of 2000000. The //dpfConst// flag is set. This field goes into the list //Class.constFields//. Constant strings fall into the same category (case str1). For //str1// an object //StringLiteral// will be created. * Case obj: Attributes //static// and //final// are set. In the constant pool we have c=(class=ClassA, name="obj", type='Object'). In //field_info()// of //obj// the attribute //ConstantValue// is not set, therefore the //dpfConst// flag won't be set either. //obj// goes into the list //Class.classFields//. * Case str2 and f: Attributes //static// and //final// are set. In //field_info()// the attribute //ConstantValue// is not set, therefore the //dpfConst// flag won't be set either. This field goes into the list //Class.classFields//. * Case c: //final// is set. In the constant pool we have c=(class=ClassA, name="c", type='I'), it's not linked to a value. That happens only in ////. There, //c// is linked to the object of type //StdConstant// with a value of 3'000'000. In //field_info()// of //c// the attribute //ConstantValue// is not set, therefore the //dpfConst// flag is not set either. This field goes into the list //Class.instFields//. * Case d: //final// is set. In the constant pool we have d=(class=ClassA, name="d", type='I'), it's not linked to a value. That happens only in ////. There, //d// is linked to the object of type //StdConstant// with a value of 4'000'000. In //field_info()// of //d// the attribute //ConstantValue// is not set, therefore the //dpfConst// flag is not set either. This field goes into the list //Class.instFields//. * Case e: same as case b For interfaces we get: * Case x: same as case b * Case str3: same as case str1 * Case str4: same as case str2 Important: When generating the SSA loading of a constant is translated with //sCloadConst//. If the constant is of type boolean, byte, short or int, which are not placed in the constant pool but in the code directly, a new object //StdConstant// must be created with the appropriate value and no name. In all other cases //sCloadConst// references the constant object built by the class file reader. ===== Methods ===== All reference types can have methods, even arrays as they inherit from //java/lang/Object//. The methods get sorted for building the type descriptors, see [[.:type_descriptor|Type Descriptor]]. ===== Locals ===== Local variables within a method are dealt with in a separate section of the bytecode, the ''local variable table''. First of all it contains information about the slot the variable occupies together with the range where the variable is defined. Different locals might occupy the same slot, even with different types.