KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > bytecode > ConstantPool


1 // Copyright (c) 1997 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.bytecode;
5
6 /** Manages a pool of constants, as used in .class files and Java interpreters.
7  * @author Per Bothner
8  */

9
10 public class ConstantPool
11 {
12   static public final byte CLASS = 7;
13   static public final byte FIELDREF = 9;
14   static public final byte METHODREF = 10;
15   static public final byte INTERFACE_METHODREF = 11;
16   static public final byte STRING = 8;
17   static public final byte INTEGER = 3;
18   static public final byte FLOAT = 4;
19   static public final byte LONG = 5;
20   static public final byte DOUBLE = 6;
21   static public final byte NAME_AND_TYPE = 12;
22   static public final byte UTF8 = 1;
23
24   /** The entries in the constant pool.
25    * The first element (constant_pool[0]) is an unused dummy. */

26   CpoolEntry[] pool;
27
28   /** Number of elements in the constant pool, not counting
29    * the initial dummy element (with index 0). */

30   int count;
31
32   public final int getCount()
33   {
34     return count;
35   }
36
37   /**
38    * Get the index'th entry in pool.
39    * Will throw ArrayIndexOutOfBoundsException on an invalid index
40    */

41   public final CpoolEntry getPoolEntry(int index)
42   {
43     return pool[index];
44   }
45
46   boolean locked;
47
48   CpoolEntry[] hashTab;
49
50   void rehash ()
51   {
52     if (hashTab == null && count > 0)
53       {
54     // Entries may not have been hashed before. Make sure they are now.
55
for (int i = pool.length; --i >= 0; )
56       {
57         CpoolEntry entry = pool[i];
58         // Make sure entry.hash is not the default value 0.
59
if (entry != null)
60           entry.hashCode();
61       }
62       }
63
64     hashTab = new CpoolEntry[count < 5 ? 101 : 2 * count];
65     if (pool != null)
66       {
67     for (int i = pool.length; --i >= 0; )
68       {
69         CpoolEntry entry = pool[i];
70         if (entry != null)
71           entry.add_hashed (this);
72       }
73       }
74   }
75
76   public CpoolUtf8 addUtf8 (String JavaDoc s)
77   {
78     s = s.intern();
79     int h = s.hashCode();
80
81     // Check if we already have a matching CONSTANT_Utf8.
82
if (hashTab == null)
83       rehash();
84
85     int index = (h & 0x7FFFFFFF) % hashTab.length;
86     for (CpoolEntry entry = hashTab[index]; entry != null; entry = entry.next)
87       {
88     if (h == entry.hash && entry instanceof CpoolUtf8)
89       {
90         CpoolUtf8 utf = (CpoolUtf8) entry;
91         if (utf.string == s)
92           return utf;
93       }
94       }
95     if (locked)
96       throw new Error JavaDoc("adding new Utf8 entry to locked contant pool: "+s);
97     return new CpoolUtf8(this, h, s);
98   }
99
100   public CpoolClass addClass (ObjectType otype)
101   {
102     return addClass(addUtf8(otype.getInternalName()));
103   }
104
105   public CpoolClass addClass (String JavaDoc name)
106   {
107     return addClass(addUtf8(name.replace('.', '/')));
108   }
109
110   public CpoolClass addClass (CpoolUtf8 name)
111   {
112     int h = CpoolClass.hashCode(name);
113
114     // Check if we already have a matching CONSTANT_Class.
115
if (hashTab == null)
116       rehash();
117     int index = (h & 0x7FFFFFFF) % hashTab.length;
118     for (CpoolEntry entry = hashTab[index]; entry != null; entry = entry.next)
119       {
120     if (h == entry.hash && entry instanceof CpoolClass)
121       {
122         CpoolClass ent = (CpoolClass) entry;
123         if (ent.name == name)
124           return ent;
125       }
126       }
127     return new CpoolClass (this, h, name);
128   }
129
130   CpoolValue1 addValue1 (int tag, int val)
131   {
132     int h = CpoolValue1.hashCode(val);
133
134     // Check if we already have a matching CONSTANT_Integer.
135
if (hashTab == null)
136       rehash();
137     int index = (h & 0x7FFFFFFF) % hashTab.length;
138     for (CpoolEntry entry = hashTab[index]; entry != null; entry = entry.next)
139       {
140     if (h == entry.hash && entry instanceof CpoolValue1)
141       {
142         CpoolValue1 ent = (CpoolValue1) entry;
143         if (ent.tag == tag && ent.value == val)
144           return ent;
145       }
146       }
147     return new CpoolValue1 (this, tag, h, val);
148   }
149
150   CpoolValue2 addValue2 (int tag, long val)
151   {
152     int h = CpoolValue2.hashCode(val);
153
154     // Check if we already have a matching CONSTANT_Integer.
155
if (hashTab == null)
156       rehash();
157     int index = (h & 0x7FFFFFFF) % hashTab.length;
158     for (CpoolEntry entry = hashTab[index]; entry != null; entry = entry.next)
159       {
160     if (h == entry.hash && entry instanceof CpoolValue2)
161       {
162         CpoolValue2 ent = (CpoolValue2) entry;
163         if (ent.tag == tag && ent.value == val)
164           return ent;
165       }
166       }
167     return new CpoolValue2 (this, tag, h, val);
168   }
169
170   public CpoolValue1 addInt (int val)
171   {
172     return addValue1(INTEGER, val);
173   }
174
175   public CpoolValue2 addLong (long val)
176   {
177     return addValue2(LONG, val);
178   }
179
180   public CpoolValue1 addFloat (float val)
181   {
182     return addValue1(FLOAT, Float.floatToIntBits(val));
183   }
184
185   public CpoolValue2 addDouble (double val)
186   {
187     return addValue2(DOUBLE, Double.doubleToLongBits(val));
188   }
189
190   public final CpoolString addString (String JavaDoc string)
191   {
192     return addString(addUtf8(string));
193   }
194
195   public CpoolString addString (CpoolUtf8 str)
196   {
197     int h = CpoolString.hashCode (str);
198
199     // Check if we already have a matching CONSTANT_String.
200
if (hashTab == null)
201       rehash();
202     int index = (h & 0x7FFFFFFF) % hashTab.length;
203     for (CpoolEntry entry = hashTab[index]; entry != null; entry = entry.next)
204       {
205     if (h == entry.hash && entry instanceof CpoolString)
206       {
207         CpoolString ent = (CpoolString) entry;
208         if (ent.str == str)
209           return ent;
210       }
211       }
212     return new CpoolString (this, h, str);
213   }
214
215   public CpoolNameAndType addNameAndType (Method method)
216   {
217     CpoolUtf8 name = addUtf8(method.getName());
218     CpoolUtf8 type = addUtf8(method.getSignature ());
219     return addNameAndType(name, type);
220   }
221
222   public CpoolNameAndType addNameAndType (Field field)
223   {
224     CpoolUtf8 name = addUtf8(field.getName());
225     CpoolUtf8 type = addUtf8(field.getSignature ());
226     return addNameAndType(name, type);
227   }
228
229   public CpoolNameAndType
230   addNameAndType (CpoolUtf8 name, CpoolUtf8 type)
231   {
232     int h = CpoolNameAndType.hashCode (name, type);
233
234     // Check if we already have a matching CONSTANT_Integer.
235
if (hashTab == null)
236       rehash();
237     int index = (h & 0x7FFFFFFF) % hashTab.length;
238     for (CpoolEntry entry = hashTab[index]; entry != null; entry = entry.next)
239       {
240     if (h == entry.hash
241         && entry instanceof CpoolNameAndType
242         && ((CpoolNameAndType)entry).name == name
243         && ((CpoolNameAndType)entry).type == type)
244       return (CpoolNameAndType)entry;
245       }
246     return new CpoolNameAndType(this, h, name, type);
247   }
248
249   public CpoolRef
250   addRef (int tag, CpoolClass clas, CpoolNameAndType nameAndType)
251   {
252     int h = CpoolRef.hashCode (clas, nameAndType);
253
254     // Check if we already have a matching CONSTANT_Integer.
255
if (hashTab == null)
256       rehash();
257     int index = (h & 0x7FFFFFFF) % hashTab.length;
258     for (CpoolEntry entry = hashTab[index]; entry != null; entry = entry.next)
259       {
260     if (h == entry.hash && entry instanceof CpoolRef)
261       {
262         CpoolRef ref = (CpoolRef) entry;
263         if (ref.tag == tag
264         && ref.clas == clas
265         && ref.nameAndType== nameAndType)
266           return ref;
267       }
268       }
269     return new CpoolRef (this, h, tag, clas, nameAndType);
270   }
271
272   public CpoolRef addMethodRef (Method method)
273   {
274     CpoolClass clas = addClass(method.classfile.this_name);
275     int tag;
276     if ((method.getDeclaringClass().getModifiers() & Access.INTERFACE) == 0)
277       tag = 10; // CONSTANT_Methodref
278
else
279       tag = 11; // CONSTANT_InterfaceMethodref
280
CpoolNameAndType nameType = addNameAndType(method);
281     return addRef(tag, clas, nameType);
282   }
283
284   public CpoolRef addFieldRef (Field field)
285   {
286     CpoolClass clas = addClass(field.owner.this_name);
287     int tag = 9; // CONSTANT_Fieldref
288
CpoolNameAndType nameType = addNameAndType(field);
289     return addRef(tag, clas, nameType);
290   }
291
292   void write (java.io.DataOutputStream JavaDoc dstr) throws java.io.IOException JavaDoc
293   {
294     dstr.writeShort(count+1);
295     for (int i = 1; i <= count; i++)
296       {
297     CpoolEntry entry = pool[i];
298     if (entry != null)
299       entry.write (dstr);
300       }
301     locked = true;
302   }
303
304   /** Get or create a CpoolEntry at a given index.
305    * If there is an existing entry, it must match the tag.
306    * If not, a new one is create of the class appropriate for the tag.
307    */

308   CpoolEntry getForced(int index, int tag)
309   {
310     index = index & 0xffff;
311     CpoolEntry entry = pool[index];
312     if (entry == null)
313       {
314     if (locked)
315       throw new Error JavaDoc("adding new entry to locked contant pool");
316     switch (tag)
317       {
318       case UTF8: entry = new CpoolUtf8(); break;
319       case INTEGER:
320       case FLOAT: entry = new CpoolValue1(tag); break;
321       case LONG:
322       case DOUBLE: entry = new CpoolValue2(tag); break;
323       case CLASS: entry = new CpoolClass(); break;
324       case STRING: entry = new CpoolString(); break;
325       case FIELDREF:
326       case METHODREF:
327       case INTERFACE_METHODREF: entry = new CpoolRef(tag); break;
328       case NAME_AND_TYPE: entry = new CpoolNameAndType();
329       }
330     pool[index] = entry;
331     entry.index = index;
332       }
333     else if (entry.getTag() != tag)
334       throw new ClassFormatError JavaDoc("conflicting constant pool tags at "+index);
335     return entry;
336   }
337
338   public ConstantPool () { }
339
340   public ConstantPool (java.io.DataInputStream JavaDoc dstr)
341        throws java.io.IOException JavaDoc
342   {
343     count = dstr.readUnsignedShort() - 1;
344     pool = new CpoolEntry[count+1];
345     for (int i = 1; i <= count; i++)
346       {
347     byte tag = dstr.readByte();
348     CpoolEntry entry = getForced(i, tag);
349     switch (tag)
350       {
351       case UTF8:
352         ((CpoolUtf8) entry).string = dstr.readUTF();
353         break;
354       case INTEGER:
355       case FLOAT:
356         ((CpoolValue1) entry).value = dstr.readInt();
357         break;
358       case LONG:
359       case DOUBLE:
360         ((CpoolValue2) entry).value = dstr.readLong();
361         i++;
362         break;
363       case CLASS:
364         ((CpoolClass) entry).name =
365           (CpoolUtf8) getForced(dstr.readUnsignedShort(), UTF8);
366         break;
367       case STRING:
368         ((CpoolString) entry).str =
369           (CpoolUtf8) getForced(dstr.readUnsignedShort(), UTF8);
370         break;
371       case FIELDREF:
372       case METHODREF:
373       case INTERFACE_METHODREF:
374         CpoolRef ref = (CpoolRef) entry;
375         ref.clas = (CpoolClass) getForced(dstr.readUnsignedShort(), CLASS);
376         ref.nameAndType = (CpoolNameAndType)
377           getForced(dstr.readUnsignedShort(), NAME_AND_TYPE);
378         break;
379       case NAME_AND_TYPE:
380         CpoolNameAndType ntyp = (CpoolNameAndType) entry;
381         ntyp.name = (CpoolUtf8) getForced(dstr.readUnsignedShort(), UTF8);
382         ntyp.type = (CpoolUtf8) getForced(dstr.readUnsignedShort(), UTF8);
383         break;
384       }
385       }
386   }
387 }
388
Popular Tags