Brought to you by EarthWeb
ITKnowledge Logo Login Graphic Click Here!
Click Here!
ITKnowledge
Find:
 
EXPERT SEARCH ----- nav

EarthWeb Direct

EarthWeb sites: other sites

Previous Table of Contents Next


Fields

Only two parts of the file are left: the fields and the methods. Let’s look at the fields first. It’s not at all uncommon for a class to have many fields. You therefore need to loop through all the fields with a for loop. Inside the loop, you check the access specifiers, the name, and the type of each field.

To read the name of the field, you simply read the UTF8 structure in the constant pool at the field’s name index. The type of the field requires more effort. Although it is stored as a UTF8 string in the constant pool at the FieldInfo’s descriptorIndex, the UTF8 string needs to be decoded first. Primitive types like int or char are encoded as single letters. For example, an int is the capital letter I. Table 4-4 lists the encodings for the primitive types.

Table 4-4 Primitive type encodings

B byte
C char
D double
F float
I int
J long
S short
Z boolean

Class types are encoded as the capital letter L, followed by the fully qualified class name, followed by a semicolon. Furthermore, for historical reasons, the periods in the fully qualified class name change to forward slashes. Therefore, inside the constant pool, the String class is written as Ljava/lang/String;, the Object class is written as Ljava/lang/Object;, the Vector class is written Ljava/util/Vector;, and so on. Converting this into the format you expect is easy. Just trim the first and last characters of the string with the substring() method and use the replace() method to change the slashes to periods like this:

   String s = “Ljava/lang/String;”;
   String r = d.substring(1, r.length() - 1);
   r = r.replace(‘/’, ‘.’);

The final type you need to deal with are the array types. These are encoded by prefixing the type of the array with left bracket signs ([), one for each dimension in the array. Thus, a double[] array is encoded as [double. A String[][] array is encoded as [[Ljava/lang/String;. To decode array types, you first count the number of left brackets and then recursively call the decodeDescriptor() method. Listing 4-30 shows the complete decodeDescriptor() method. It takes a single argument — the string to be decoded — and returns the decoded string.

Listing 4-30 The decodeDescriptor() method

   public String decodeDescriptor(String d) {
    if (d.equals(“B”)) return “byte”;
    else if (d.equals(“C”)) return “char”;
    else if (d.equals(“D”)) return “double”;
    else if (d.equals(“F”)) return “float”;
    else if (d.equals(“I”)) return “int”;
    else if (d.equals(“J”)) return “long”;
    else if (d.equals(“S”)) return “short”;
    else if (d.equals(“Z”)) return “boolean”;
    else if (d.startsWith(“L”)) {  // object
     String r = d.substring(1, r.length() - 1);
     r = r.replace(‘/’, ‘.’);
     return r;
    }
    else if (d.startsWith(“[“)) { // array
     int dimensions = d.lastIndexOf(‘[‘) + 1;
     String type = decodeDescriptor(d.substring(dimensions));
     for (int i=0; i < dimensions; i++) {
      type += “[]”;
     }
     return type;
    }
    else {
     throw new ClassFormatError(“Unrecognized Type: “ + d);
    }

   }

Now that you have a method to decode descriptors, it’s easy to finish the writeFields() method. Listing 4-31 demonstrates.

Listing 4-31 The writeFields() method

   public void writeFields() {

    for (int i = 0; i < fields.length; i++) {
     // indent two spaces
     theOutput.print(“  “);

     // print the access specifiers
     if (fields[i].isPublic()) theOutput.print(“public “);
     if (fields[i].isPrivate()) theOutput.print(“private “);
     if (fields[i].isProtected()) theOutput.print(“protected “);
     if (fields[i].isStatic()) theOutput.print(“static “);
     if (fields[i].isVolatile()) theOutput.print(“volatile “);
     if (fields[i].isTransient()) theOutput.print(“transient “);
     if (fields[i].isFinal()) theOutput.print(“final “);

     //print the type
     String descriptor = thePool.readUTF8(fields[i].descriptorIndex());
     theOutput.print(decodeDescriptor(descriptor) + “ “);

     //print the name
     theOutput.print(thePool.readUTF8(fields[i].nameIndex()));

     theOutput.println(“;”);

    }

   }


Note:  I debated whether to include the code to read a field info structure and convert it into a string in the FieldInfo class or in the Disassembler class. Although it would make somewhat more sense to encapsulate the code in the FieldInfo class, it can be decoded only if each FieldInfo object carries a reference to its constant pool.


Previous Table of Contents Next
HomeAbout UsSearchSubscribeAdvertising InfoContact UsFAQs
Use of this site is subject to certain Terms & Conditions.
Copyright (c) 1996-1999 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.