1    
2    /*
3    
4      The author of this software is Ian Kaplan
5      Bear Products International
6      www.bearcave.com
7      iank@bearcave.com
8    
9      Copyright (c) Ian Kaplan, 1999, 2000
10   
11     See copyright file for usage and licensing
12   
13   */
14   
15   package jconst;
16   
17   import java.io.*;
18   import util.*;
19   
20   
21   /*
22    * constPool
23    *
24   
25      Read the Java JVM constant pool from the class file
26   
27      The JVM Specification, Second Edition states:
28   
29        The constant pool count (constPoolCnt) is the number of constant
30        pool table entries plus one.  A constant pool index is considered
31        valid if it is greater than zero and less than the constant pool
32        count, with the exception for constants of type long and double.
33   
34     There should be constPoolCnt-1 constant pool entries.  These
35     will be inserted into the constant pool (constPool) at
36     locations 1 ... constPoolCnt-1.
37     
38        The first entry of the constant_pool table, constant_pool[0],
39        is reserved for internal use by the Java Virtual Machine
40        implementation.  That entry is not present in the class
41        file.  The first entry in the class file is constant_pool[1];
42   
43    */
44   public class constPool extends dataRead implements constPoolTags {
45     private int constPoolCnt;
46     private constBase constPool[] = null;
47   
48     public constPool( DataInputStream dStream ) {
49   
50       constPoolCnt = readU2( dStream );
51   
52       // The constant pool array is an array of references to
53       // the base class object.  References 1..constPoolCnt-1
54       // are valid and are filled in when the constant pool
55       // is read.
56       constPool = new constBase[ constPoolCnt ];
57   
58       readConstPool( dStream );
59       resolveConstPool();
60     } // constPool constructor
61   
62   
63     //
64     // constPoolElem
65     //
66     // Return the constant pool object at index ix.
67     // Note that only constant pool indices greater than
68     // zero are valid.
69     //
70     public constBase constPoolElem( int ix )
71     {
72       constBase elem = null;
73   
74       if (ix > 0 && ix < constPool.length) {
75         elem = constPool[ix];
76       }
77       return elem;
78     } // constPoolElem
79   
80   
81     //
82     // allocconstEntry
83     //
84     // Allocate the constant object associated with the tag.
85     //
86     private constBase allocConstEntry( int tag ) {
87       constBase obj = null;
88   
89       switch ( tag ) {
90       case CONSTANT_Utf8:
91         obj = new constUtf8();
92         break;
93       case CONSTANT_Integer:
94         obj = new constInt();
95         break;
96       case CONSTANT_Float:
97         obj = new constFloat();
98         break;
99       case CONSTANT_Long:
100        obj = new constLong();
101        break;
102      case CONSTANT_Double:
103        obj = new constDouble();
104        break;
105      case CONSTANT_Class:
106      case CONSTANT_String:
107        obj = new constClass_or_String();
108        break;
109      case CONSTANT_Fieldref:
110      case CONSTANT_Methodref:
111      case CONSTANT_InterfaceMethodref:
112        obj = new constRef();
113        break; 
114      case CONSTANT_NameAndType:
115        obj = new constName_and_Type_info();
116        break;
117      default:
118        System.out.println("allocConstEntry: bad tag value = " + tag);
119        break;
120      } // switch
121  
122      if (obj != null) {
123        obj.tag = tag;
124      }
125      return obj;
126    } // allocConstEntry
127  
128  
129    //
130    // resolveConstPool
131    //
132    //
133    // A number of the constant pool classes contain indices that
134    // refer to other elements in the constant pool.  Convert these
135    // to references, using the set_ref() method.  This method is
136    // implemented for all classes, but only does something when it
137    // is appropriate.
138    //
139    //
140    private void resolveConstPool() {
141      for (int i = 1; i < constPoolCnt; i++) {
142        if (constPool[i] != null)
143  	constPool[i].set_ref(constPool);
144      }    
145    } // resolveConstPool
146  
147  
148    /**
149       Read the JVM class file constant pool and put
150       it in the internal constant pool.
151  <p>
152       There is a special case in constant pool construction.
153       CONSTANT_Long_info and CONSTANT_Double_info structures
154       take up tow elements in the constant pool table 
155       (constPool).  See JVM Spec. 4.4.5.  As noted in a footnote
156       "In retrospect, making 8-byte constants take two constant
157       pool entries was a poor choice."  The extra constant pool
158       entry is unused (and is set to null here).
159    */
160    private void readConstPool(DataInputStream dStream) {
161      int tag;
162      constBase constObj;
163  
164      for (int i = 1; i < constPoolCnt; i++) {
165        tag = readU1( dStream );
166        if (tag > 0) {
167  	constObj = allocConstEntry( tag );
168  	constObj.read( dStream );
169  	constPool[i] = constObj;
170  	if (constObj instanceof constLong || 
171  	    constObj instanceof constDouble) {
172  	  i++;
173  	  constPool[i] = null;
174  	}
175        }
176        else {
177  	System.out.println("readConstPool: tag == 0 at constPool index " + i );
178        }
179  
180      }
181    } // readConstPool
182  
183  
184    //
185    // pr
186    // 
187    // Display constant pool count and the contents of the constant pool
188    //
189    public void pr() {
190      System.out.println("constant pool count = " + constPoolCnt + 
191  		       " (size = " + (constPoolCnt-1) + ")");
192      for (int i = 1; i < constPoolCnt; i++) {
193        System.out.print( i + " ");
194        if (constPool[i] != null) {
195  	constPool[i].pr();
196  	System.out.println();
197        }
198      }
199    }
200  
201  } // constPool
202