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


Constant pool

The constant pool is a data structure that stores all the constants in a program, not just literals like 1.0 or 72, but also class structures, method references, and the names and types of variables. The disassembler needs to make frequent reference back to this data structure when parsing later parts of the file. Many other entries in the .class file simply refer back to constants stored in the constant pool. It is therefore necessary to create a data structure to hold the constants for later reference.

The largest difficulty in this endeavor is that the constant pool has to hold values of 11 different types. To make matters worse, six of those types are reference types and five are primitive types. Because this is relatively complex, I’m going to push all the details into a new class called ConstantPool. The Disassembler class will simply call the ConstantPool() constructor, as shown in Listing 4-10. The ConstantPool() constructor will read the data out of theInput and parse it, and a new ConstantPool object will be stored in the field thePool.

Listing 4-10 The ConstantPool() constructor

   ConstantPool thePool;

   void readConstantPool() throws IOException {

    thePool = new ConstantPool(theInput);

   }

The exact size of the constant pool depends on what’s inside it. The first two bytes of this part of the file are an unsigned short specifying the number of entries in the constant pool. This number must be greater than zero. The first constant pool entry is reserved for the virtual machine’s use. Therefore, there is actually one less than this number of actual entries to be read. However, entries of different types can have different sizes.

Listing 4-11 is the ConstantPool class. This class does two things: first, it reads the constant pool from the file; second, it responds to requests for items from the constant pool.

The ConstantPool class is implemented as an array of PoolEntry objects. Listing 4-12 is the PoolEntry class. A PoolEntry object can hold one item that has one of the 11 different types and classes that can be stored in the constant pool. The ConstantPool constructor first reads two bytes from the InputStream as an unsigned short. This specifies the number of entries in the ConstantPool so that it can decide how large to make the PoolEntry array. Then, it passes InputStream to the PoolEntry() constructor enough times to fill the array. The PoolEntry() constructor determines the type of that entry in the pool and reads the right number of bytes for that type.

To read a particular entry from the constant pool, you call the properly typed read method of ConstantPool — for example, readDouble(int i) to get a double constant from the pool. These methods retrieve the right PoolEntry from the array and then call that entry’s matching read method.

All information about the type of a PoolEntry is stored in the PoolEntry itself. The user, however, will generally need to know the type of the entry being requested. If the user requests the wrong type from a PoolEntry, then the PoolEntry will throw a ClassFormatError.


Note:  This is not the only way that I could have structured this program. Another possibility would have been to make PoolEntry an abstract class with an abstract read method. There would be subclasses for double, float, ClassInfo, and the other types.

Listing 4-11 The ConstantPool class

   import java.io.*;

   public class ConstantPool {

    PoolEntry[] thePool;

    public ConstantPool(DataInputStream dis) throws IOException {
     int length = dis.readUnsignedShort();
     thePool = new PoolEntry[length];
     for (int i = 1; i < length; i++) {
      thePool[i] = new PoolEntry(dis);
      // Doubles and longs take two pool entries
      // see Java VM Spec., p. 98
      if (thePool[i].tag == PoolEntry.cDouble || thePool[i].tag == PoolEntry.cLong)
       i++;
     }

    }

    public PoolEntry read(int i) {
     return thePool[i];
    }

    public String readUTF8(int i) {
     return thePool[i].readUTF8();
    }

    public int readInteger(int i) {
     return thePool[i].readInteger();
    }

    public float readFloat(int i) {
     return thePool[i].readFloat();
    }

    public double readDouble(int i) {
     return thePool[i].readDouble();
    }

    public ClassInfo readClassInfo(int i) {
     return thePool[i].readClassInfo();
    }

    public RefInfo readMethodRef(int i) {
     return thePool[i].readMethodRef();
    }

    public RefInfo readInterfaceMethodRef(int i) {
     return thePool[i].readInterfaceMethodRef();
    }

    public NameAndType readNameAndType(int i) {
     return thePool[i].readNameAndType();
    }

    public int howMany() {
     return thePool.length;
    }

    public String toString() {
     String result = “”;
     for (int i = 1; i < thePool.length; i++) {
      result += i + “:  “ + thePool[i].toString() + “\n”;
      // Doubles and longs take two pool entries
      // see Java VM Spec., p. 98
      if (thePool[i].tag == PoolEntry.cDouble || thePool[i].tag == PoolEntry.cLong) i++;
     }

     return result;

    }

   }


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.