![]() |
|||
![]() ![]() |
![]() |
|
![]() |
SuperclassImmediately following the index of this class, youll find the index into the constant pool for the ClassInfo structure of this classs superclass (Listing 4-18). Reading this value is almost identical to the previous method. However, if this class does not have a superclass (that is, if this is java.lang.Object, the only class without a superclass), then the index into the constant pool will be zero. You therefore have to watch out for this special case. If the index is zero, then you should set superclass to null. Listing 4-18 readSuperclass() ClassInfo superclass; void readSuperclass() throws IOException { int index = theInput.readUnsignedShort(); if (index == 0) { superclass = null; } else { superclass = thePool.readClassInfo(index); } } InterfacesA single class can implement multiple interfaces. First, an unsigned short tells you how many interfaces that this class implements (possibly zero). There are exactly that many unsigned short indices in the constant pool. Each index points to a ClassInfo structure for the implemented interface. Listing 4-19 is the fleshed-out readInterfaces() method. The interfaces are read, resolved, and stored in a new field array called interfaces. Listing 4-19 The readInterfaces() method ClassInfo[] interfaces; void readInterfaces() throws IOException { interfaces = new ClassInfo[theInput.readUnsignedShort()]; for (int i =0; i< interfaces.length; i++) { interfaces[i] = thePool.readClassInfo(i); } AttributesThe last thing you read from a .class file is the classs attributes. Before you get to a classs attributes, you have to read its fields and methods. However, each field and method also has its own attributes table. Therefore, you should develop the classes needed to read attributes before you need them. This class will read the attributes of the fields, the methods, and the class itself. An attribute table consists of a specified number of attribute_info structures (see Listing 4-20). Each attribute_info structure consists of one unsigned short that is the name index for this attribute. Its an index into the constant pool. Next, theres a 4-byte unsigned int that gives you the length of the attributes data. Finally, theres an array of data. Listing 4-20 AttributeInfo import java.io.*; public class AttributeInfo { int nameIndex; byte[] data; public AttributeInfo(DataInputStream dis) throws IOException { nameIndex = dis.readUnsignedShort(); data = new byte[dis.readInt()]; int bytesRead = dis.read(data); if (bytesRead != data.length) { throw new ClassFormatError(Insufficioent bytes in attribute); } } } Listing 4-21 is a filled-in readAttributes() method for the Disassembler class. An array of AttributeInfo structures holds the different attributes. Listing 4-21 readAttributes() AttributeInfo[] attributes; void readAttributes() throws IOException { attributes = new AttributeInfo[theInput.readUnsignedShort()]; for (int i = 0; i < attributes.length; i++) { attributes[i] = new AttributeInfo(dis); } } FieldsAfter youve read the interfaces, you next read the classs fields. Some classes have no fields. For example, the HelloWorld program has only a method. An unsigned short tells you how many fields there are in the class. Then you read that many FieldInfo structures from the file. A FieldInfo structure is composed of five items. The first unsigned short is the access flags for the field. These tell you whether the field is public, private, protected, static, final, volatile, and/or transient. Table 4-3 lists the bit masks for each of these modifiers. As usual, the bit mask values are chosen so that the bitwise operators can easily pick out individual values. Note that not all of the possible combinations of flags are allowed. For example, a field cannot be both public and private. Each flag is exactly equivalent to a Java keyword, which may modify a field.
|
![]() |
|