• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License.  Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */
15 
16 package javassist.bytecode;
17 
18 import java.io.DataInputStream;
19 import java.io.DataOutputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.PrintWriter;
22 import java.io.IOException;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.Map;
26 import java.util.Set;
27 
28 import javassist.CtClass;
29 
30 /**
31  * Constant pool table.
32  */
33 public final class ConstPool {
34     LongVector items;
35     int numOfItems;
36     HashMap classes;
37     HashMap strings;
38     ConstInfo[] constInfoCache;
39     int[] constInfoIndexCache;
40     int thisClassInfo;
41 
42     private static final int CACHE_SIZE = 32;
43 
44     /**
45      * A hash function for CACHE_SIZE
46      */
hashFunc(int a, int b)47     private static int hashFunc(int a, int b) {
48         int h = -2128831035;
49         final int prime = 16777619;
50         h = (h ^ (a & 0xff)) * prime;
51         h = (h ^ (b & 0xff)) * prime;
52 
53         // changing the hash key size from 32bit to 5bit
54         h = (h >> 5) ^ (h & 0x1f);
55         return h & 0x1f;    // 0..31
56     }
57 
58     /**
59      * <code>CONSTANT_Class</code>
60      */
61     public static final int CONST_Class = ClassInfo.tag;
62 
63     /**
64      * <code>CONSTANT_Fieldref</code>
65      */
66     public static final int CONST_Fieldref = FieldrefInfo.tag;
67 
68     /**
69      * <code>CONSTANT_Methodref</code>
70      */
71     public static final int CONST_Methodref = MethodrefInfo.tag;
72 
73     /**
74      * <code>CONSTANT_InterfaceMethodref</code>
75      */
76     public static final int CONST_InterfaceMethodref
77                                         = InterfaceMethodrefInfo.tag;
78 
79     /**
80      * <code>CONSTANT_String</code>
81      */
82     public static final int CONST_String = StringInfo.tag;
83 
84     /**
85      * <code>CONSTANT_Integer</code>
86      */
87     public static final int CONST_Integer = IntegerInfo.tag;
88 
89     /**
90      * <code>CONSTANT_Float</code>
91      */
92     public static final int CONST_Float = FloatInfo.tag;
93 
94     /**
95      * <code>CONSTANT_Long</code>
96      */
97     public static final int CONST_Long = LongInfo.tag;
98 
99     /**
100      * <code>CONSTANT_Double</code>
101      */
102     public static final int CONST_Double = DoubleInfo.tag;
103 
104     /**
105      * <code>CONSTANT_NameAndType</code>
106      */
107     public static final int CONST_NameAndType = NameAndTypeInfo.tag;
108 
109     /**
110      * <code>CONSTANT_Utf8</code>
111      */
112     public static final int CONST_Utf8 = Utf8Info.tag;
113 
114     /**
115      * Represents the class using this constant pool table.
116      */
117     public static final CtClass THIS = null;
118 
119     /**
120      * Constructs a constant pool table.
121      *
122      * @param thisclass         the name of the class using this constant
123      *                          pool table
124      */
ConstPool(String thisclass)125     public ConstPool(String thisclass) {
126         items = new LongVector();
127         numOfItems = 0;
128         addItem(null);          // index 0 is reserved by the JVM.
129         classes = new HashMap();
130         strings = new HashMap();
131         constInfoCache = new ConstInfo[CACHE_SIZE];
132         constInfoIndexCache = new int[CACHE_SIZE];
133         thisClassInfo = addClassInfo(thisclass);
134     }
135 
136     /**
137      * Constructs a constant pool table from the given byte stream.
138      *
139      * @param in        byte stream.
140      */
ConstPool(DataInputStream in)141     public ConstPool(DataInputStream in) throws IOException {
142         classes = new HashMap();
143         strings = new HashMap();
144         constInfoCache = new ConstInfo[CACHE_SIZE];
145         constInfoIndexCache = new int[CACHE_SIZE];
146         thisClassInfo = 0;
147         /* read() initializes items and numOfItems, and do addItem(null).
148          */
149         read(in);
150     }
151 
prune()152     void prune() {
153         classes = new HashMap();
154         strings = new HashMap();
155         constInfoCache = new ConstInfo[CACHE_SIZE];
156         constInfoIndexCache = new int[CACHE_SIZE];
157     }
158 
159     /**
160      * Returns the number of entries in this table.
161      */
getSize()162     public int getSize() {
163         return numOfItems;
164     }
165 
166     /**
167      * Returns the name of the class using this constant pool table.
168      */
getClassName()169     public String getClassName() {
170         return getClassInfo(thisClassInfo);
171     }
172 
173     /**
174      * Returns the index of <code>CONSTANT_Class_info</code> structure
175      * specifying the class using this constant pool table.
176      */
getThisClassInfo()177     public int getThisClassInfo() {
178         return thisClassInfo;
179     }
180 
setThisClassInfo(int i)181     void setThisClassInfo(int i) {
182         thisClassInfo = i;
183     }
184 
getItem(int n)185     ConstInfo getItem(int n) {
186         return items.elementAt(n);
187     }
188 
189     /**
190      * Returns the <code>tag</code> field of the constant pool table
191      * entry at the given index.
192      */
getTag(int index)193     public int getTag(int index) {
194         return getItem(index).getTag();
195     }
196 
197     /**
198      * Reads <code>CONSTANT_Class_info</code> structure
199      * at the given index.
200      *
201      * @return  a fully-qualified class or interface name specified
202      *          by <code>name_index</code>.  If the type is an array
203      *          type, this method returns an encoded name like
204      *          <code>[java.lang.Object;</code> (note that the separators
205      *          are not slashes but dots).
206      * @see javassist.ClassPool#getCtClass(String)
207      */
getClassInfo(int index)208     public String getClassInfo(int index) {
209         ClassInfo c = (ClassInfo)getItem(index);
210         if (c == null)
211             return null;
212         else
213             return Descriptor.toJavaName(getUtf8Info(c.name));
214     }
215 
216     /**
217      * Reads the <code>name_index</code> field of the
218      * <code>CONSTANT_NameAndType_info</code> structure
219      * at the given index.
220      */
getNameAndTypeName(int index)221     public int getNameAndTypeName(int index) {
222         NameAndTypeInfo ntinfo = (NameAndTypeInfo)getItem(index);
223         return ntinfo.memberName;
224     }
225 
226     /**
227      * Reads the <code>descriptor_index</code> field of the
228      * <code>CONSTANT_NameAndType_info</code> structure
229      * at the given index.
230      */
getNameAndTypeDescriptor(int index)231     public int getNameAndTypeDescriptor(int index) {
232         NameAndTypeInfo ntinfo = (NameAndTypeInfo)getItem(index);
233         return ntinfo.typeDescriptor;
234     }
235 
236     /**
237      * Reads the <code>class_index</code> field of the
238      * <code>CONSTANT_Fieldref_info</code>,
239      * <code>CONSTANT_Methodref_info</code>,
240      * or <code>CONSTANT_Interfaceref_info</code>,
241      * structure at the given index.
242      *
243      * @since 3.6
244      */
getMemberClass(int index)245     public int getMemberClass(int index) {
246         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
247         return minfo.classIndex;
248     }
249 
250     /**
251      * Reads the <code>name_and_type_index</code> field of the
252      * <code>CONSTANT_Fieldref_info</code>,
253      * <code>CONSTANT_Methodref_info</code>,
254      * or <code>CONSTANT_Interfaceref_info</code>,
255      * structure at the given index.
256      *
257      * @since 3.6
258      */
getMemberNameAndType(int index)259     public int getMemberNameAndType(int index) {
260         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
261         return minfo.nameAndTypeIndex;
262     }
263 
264     /**
265      * Reads the <code>class_index</code> field of the
266      * <code>CONSTANT_Fieldref_info</code> structure
267      * at the given index.
268      */
getFieldrefClass(int index)269     public int getFieldrefClass(int index) {
270         FieldrefInfo finfo = (FieldrefInfo)getItem(index);
271         return finfo.classIndex;
272     }
273 
274     /**
275      * Reads the <code>class_index</code> field of the
276      * <code>CONSTANT_Fieldref_info</code> structure
277      * at the given index.
278      *
279      * @return the name of the class at that <code>class_index</code>.
280      */
getFieldrefClassName(int index)281     public String getFieldrefClassName(int index) {
282         FieldrefInfo f = (FieldrefInfo)getItem(index);
283         if (f == null)
284             return null;
285         else
286             return getClassInfo(f.classIndex);
287     }
288 
289     /**
290      * Reads the <code>name_and_type_index</code> field of the
291      * <code>CONSTANT_Fieldref_info</code> structure
292      * at the given index.
293      */
getFieldrefNameAndType(int index)294     public int getFieldrefNameAndType(int index) {
295         FieldrefInfo finfo = (FieldrefInfo)getItem(index);
296         return finfo.nameAndTypeIndex;
297     }
298 
299     /**
300      * Reads the <code>name_index</code> field of the
301      * <code>CONSTANT_NameAndType_info</code> structure
302      * indirectly specified by the given index.
303      *
304      * @param index     an index to a <code>CONSTANT_Fieldref_info</code>.
305      * @return  the name of the field.
306      */
getFieldrefName(int index)307     public String getFieldrefName(int index) {
308         FieldrefInfo f = (FieldrefInfo)getItem(index);
309         if (f == null)
310             return null;
311         else {
312             NameAndTypeInfo n = (NameAndTypeInfo)getItem(f.nameAndTypeIndex);
313             if(n == null)
314                 return null;
315             else
316                 return getUtf8Info(n.memberName);
317         }
318     }
319 
320     /**
321      * Reads the <code>descriptor_index</code> field of the
322      * <code>CONSTANT_NameAndType_info</code> structure
323      * indirectly specified by the given index.
324      *
325      * @param index     an index to a <code>CONSTANT_Fieldref_info</code>.
326      * @return  the type descriptor of the field.
327      */
getFieldrefType(int index)328     public String getFieldrefType(int index) {
329         FieldrefInfo f = (FieldrefInfo)getItem(index);
330         if (f == null)
331             return null;
332         else {
333             NameAndTypeInfo n = (NameAndTypeInfo)getItem(f.nameAndTypeIndex);
334             if(n == null)
335                 return null;
336             else
337                 return getUtf8Info(n.typeDescriptor);
338         }
339     }
340 
341     /**
342      * Reads the <code>class_index</code> field of the
343      * <code>CONSTANT_Methodref_info</code> structure
344      * at the given index.
345      */
getMethodrefClass(int index)346     public int getMethodrefClass(int index) {
347         MethodrefInfo minfo = (MethodrefInfo)getItem(index);
348         return minfo.classIndex;
349     }
350 
351     /**
352      * Reads the <code>class_index</code> field of the
353      * <code>CONSTANT_Methodref_info</code> structure
354      * at the given index.
355      *
356      * @return the name of the class at that <code>class_index</code>.
357      */
getMethodrefClassName(int index)358     public String getMethodrefClassName(int index) {
359         MethodrefInfo minfo = (MethodrefInfo)getItem(index);
360         if (minfo == null)
361             return null;
362         else
363             return getClassInfo(minfo.classIndex);
364     }
365 
366     /**
367      * Reads the <code>name_and_type_index</code> field of the
368      * <code>CONSTANT_Methodref_info</code> structure
369      * at the given index.
370      */
getMethodrefNameAndType(int index)371     public int getMethodrefNameAndType(int index) {
372         MethodrefInfo minfo = (MethodrefInfo)getItem(index);
373         return minfo.nameAndTypeIndex;
374     }
375 
376     /**
377      * Reads the <code>name_index</code> field of the
378      * <code>CONSTANT_NameAndType_info</code> structure
379      * indirectly specified by the given index.
380      *
381      * @param index     an index to a <code>CONSTANT_Methodref_info</code>.
382      * @return  the name of the method.
383      */
getMethodrefName(int index)384     public String getMethodrefName(int index) {
385         MethodrefInfo minfo = (MethodrefInfo)getItem(index);
386         if (minfo == null)
387             return null;
388         else {
389             NameAndTypeInfo n
390                 = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
391             if(n == null)
392                 return null;
393             else
394                 return getUtf8Info(n.memberName);
395         }
396     }
397 
398     /**
399      * Reads the <code>descriptor_index</code> field of the
400      * <code>CONSTANT_NameAndType_info</code> structure
401      * indirectly specified by the given index.
402      *
403      * @param index     an index to a <code>CONSTANT_Methodref_info</code>.
404      * @return  the descriptor of the method.
405      */
getMethodrefType(int index)406     public String getMethodrefType(int index) {
407         MethodrefInfo minfo = (MethodrefInfo)getItem(index);
408         if (minfo == null)
409             return null;
410         else {
411             NameAndTypeInfo n
412                 = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
413             if(n == null)
414                 return null;
415             else
416                 return getUtf8Info(n.typeDescriptor);
417         }
418     }
419 
420     /**
421      * Reads the <code>class_index</code> field of the
422      * <code>CONSTANT_InterfaceMethodref_info</code> structure
423      * at the given index.
424      */
getInterfaceMethodrefClass(int index)425     public int getInterfaceMethodrefClass(int index) {
426         InterfaceMethodrefInfo minfo
427             = (InterfaceMethodrefInfo)getItem(index);
428         return minfo.classIndex;
429     }
430 
431     /**
432      * Reads the <code>class_index</code> field of the
433      * <code>CONSTANT_InterfaceMethodref_info</code> structure
434      * at the given index.
435      *
436      * @return the name of the class at that <code>class_index</code>.
437      */
getInterfaceMethodrefClassName(int index)438     public String getInterfaceMethodrefClassName(int index) {
439         InterfaceMethodrefInfo minfo
440             = (InterfaceMethodrefInfo)getItem(index);
441         return getClassInfo(minfo.classIndex);
442     }
443 
444     /**
445      * Reads the <code>name_and_type_index</code> field of the
446      * <code>CONSTANT_InterfaceMethodref_info</code> structure
447      * at the given index.
448      */
getInterfaceMethodrefNameAndType(int index)449     public int getInterfaceMethodrefNameAndType(int index) {
450         InterfaceMethodrefInfo minfo
451             = (InterfaceMethodrefInfo)getItem(index);
452         return minfo.nameAndTypeIndex;
453     }
454 
455     /**
456      * Reads the <code>name_index</code> field of the
457      * <code>CONSTANT_NameAndType_info</code> structure
458      * indirectly specified by the given index.
459      *
460      * @param index     an index to
461      *                  a <code>CONSTANT_InterfaceMethodref_info</code>.
462      * @return  the name of the method.
463      */
getInterfaceMethodrefName(int index)464     public String getInterfaceMethodrefName(int index) {
465         InterfaceMethodrefInfo minfo
466             = (InterfaceMethodrefInfo)getItem(index);
467         if (minfo == null)
468             return null;
469         else {
470             NameAndTypeInfo n
471                 = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
472             if(n == null)
473                 return null;
474             else
475                 return getUtf8Info(n.memberName);
476         }
477     }
478 
479     /**
480      * Reads the <code>descriptor_index</code> field of the
481      * <code>CONSTANT_NameAndType_info</code> structure
482      * indirectly specified by the given index.
483      *
484      * @param index     an index to
485      *                  a <code>CONSTANT_InterfaceMethodref_info</code>.
486      * @return  the descriptor of the method.
487      */
getInterfaceMethodrefType(int index)488     public String getInterfaceMethodrefType(int index) {
489         InterfaceMethodrefInfo minfo
490             = (InterfaceMethodrefInfo)getItem(index);
491         if (minfo == null)
492             return null;
493         else {
494             NameAndTypeInfo n
495                 = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
496             if(n == null)
497                 return null;
498             else
499                 return getUtf8Info(n.typeDescriptor);
500         }
501     }
502     /**
503      * Reads <code>CONSTANT_Integer_info</code>, <code>_Float_info</code>,
504      * <code>_Long_info</code>, <code>_Double_info</code>, or
505      * <code>_String_info</code> structure.
506      * These are used with the LDC instruction.
507      *
508      * @return a <code>String</code> value or a wrapped primitive-type
509      * value.
510      */
getLdcValue(int index)511     public Object getLdcValue(int index) {
512         ConstInfo constInfo = this.getItem(index);
513         Object value = null;
514         if (constInfo instanceof StringInfo)
515             value = this.getStringInfo(index);
516         else if (constInfo instanceof FloatInfo)
517             value = new Float(getFloatInfo(index));
518         else if (constInfo instanceof IntegerInfo)
519             value = new Integer(getIntegerInfo(index));
520         else if (constInfo instanceof LongInfo)
521             value = new Long(getLongInfo(index));
522         else if (constInfo instanceof DoubleInfo)
523             value = new Double(getDoubleInfo(index));
524         else
525             value = null;
526 
527         return value;
528     }
529 
530     /**
531      * Reads <code>CONSTANT_Integer_info</code> structure
532      * at the given index.
533      *
534      * @return the value specified by this entry.
535      */
getIntegerInfo(int index)536     public int getIntegerInfo(int index) {
537         IntegerInfo i = (IntegerInfo)getItem(index);
538         return i.value;
539     }
540 
541     /**
542      * Reads <code>CONSTANT_Float_info</code> structure
543      * at the given index.
544      *
545      * @return the value specified by this entry.
546      */
getFloatInfo(int index)547     public float getFloatInfo(int index) {
548         FloatInfo i = (FloatInfo)getItem(index);
549         return i.value;
550     }
551 
552     /**
553      * Reads <code>CONSTANT_Long_info</code> structure
554      * at the given index.
555      *
556      * @return the value specified by this entry.
557      */
getLongInfo(int index)558     public long getLongInfo(int index) {
559         LongInfo i = (LongInfo)getItem(index);
560         return i.value;
561     }
562 
563     /**
564      * Reads <code>CONSTANT_Double_info</code> structure
565      * at the given index.
566      *
567      * @return the value specified by this entry.
568      */
getDoubleInfo(int index)569     public double getDoubleInfo(int index) {
570         DoubleInfo i = (DoubleInfo)getItem(index);
571         return i.value;
572     }
573 
574     /**
575      * Reads <code>CONSTANT_String_info</code> structure
576      * at the given index.
577      *
578      * @return the string specified by <code>string_index</code>.
579      */
getStringInfo(int index)580     public String getStringInfo(int index) {
581         StringInfo si = (StringInfo)getItem(index);
582         return getUtf8Info(si.string);
583     }
584 
585     /**
586      * Reads <code>CONSTANT_utf8_info</code> structure
587      * at the given index.
588      *
589      * @return the string specified by this entry.
590      */
getUtf8Info(int index)591     public String getUtf8Info(int index) {
592         Utf8Info utf = (Utf8Info)getItem(index);
593         return utf.string;
594     }
595 
596     /**
597      * Determines whether <code>CONSTANT_Methodref_info</code>
598      * structure at the given index represents the constructor
599      * of the given class.
600      *
601      * @return          the <code>descriptor_index</code> specifying
602      *                  the type descriptor of the that constructor.
603      *                  If it is not that constructor,
604      *                  <code>isConstructor()</code> returns 0.
605      */
isConstructor(String classname, int index)606     public int isConstructor(String classname, int index) {
607         return isMember(classname, MethodInfo.nameInit, index);
608     }
609 
610     /**
611      * Determines whether <code>CONSTANT_Methodref_info</code>,
612      * <code>CONSTANT_Fieldref_info</code>, or
613      * <code>CONSTANT_InterfaceMethodref_info</code> structure
614      * at the given index represents the member with the specified
615      * name and declaring class.
616      *
617      * @param classname         the class declaring the member
618      * @param membername        the member name
619      * @param index             the index into the constant pool table
620      *
621      * @return          the <code>descriptor_index</code> specifying
622      *                  the type descriptor of that member.
623      *                  If it is not that member,
624      *                  <code>isMember()</code> returns 0.
625      */
isMember(String classname, String membername, int index)626     public int isMember(String classname, String membername, int index) {
627         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
628         if (getClassInfo(minfo.classIndex).equals(classname)) {
629             NameAndTypeInfo ntinfo
630                 = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
631             if (getUtf8Info(ntinfo.memberName).equals(membername))
632                 return ntinfo.typeDescriptor;
633         }
634 
635         return 0;       // false
636     }
637 
638     /**
639      * Determines whether <code>CONSTANT_Methodref_info</code>,
640      * <code>CONSTANT_Fieldref_info</code>, or
641      * <code>CONSTANT_InterfaceMethodref_info</code> structure
642      * at the given index has the name and the descriptor
643      * given as the arguments.
644      *
645      * @param membername        the member name
646      * @param desc              the descriptor of the member.
647      * @param index             the index into the constant pool table
648      *
649      * @return          the name of the target class specified by
650      *                  the <code>..._info</code> structure
651      *                  at <code>index</code>.
652      *                  Otherwise, null if that structure does not
653      *                  match the given member name and descriptor.
654      */
eqMember(String membername, String desc, int index)655     public String eqMember(String membername, String desc, int index) {
656         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
657         NameAndTypeInfo ntinfo
658                 = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
659         if (getUtf8Info(ntinfo.memberName).equals(membername)
660             && getUtf8Info(ntinfo.typeDescriptor).equals(desc))
661             return getClassInfo(minfo.classIndex);
662         else
663             return null;       // false
664     }
665 
addItem(ConstInfo info)666     private int addItem(ConstInfo info) {
667         items.addElement(info);
668         return numOfItems++;
669     }
670 
671     /**
672      * Copies the n-th item in this ConstPool object into the destination
673      * ConstPool object.
674      * The class names that the item refers to are renamed according
675      * to the given map.
676      *
677      * @param n                 the <i>n</i>-th item
678      * @param dest              destination constant pool table
679      * @param classnames        the map or null.
680      * @return the index of the copied item into the destination ClassPool.
681      */
copy(int n, ConstPool dest, Map classnames)682     public int copy(int n, ConstPool dest, Map classnames) {
683         if (n == 0)
684             return 0;
685 
686         ConstInfo info = getItem(n);
687         return info.copy(this, dest, classnames);
688     }
689 
addConstInfoPadding()690     int addConstInfoPadding() {
691         return addItem(new ConstInfoPadding());
692     }
693 
694     /**
695      * Adds a new <code>CONSTANT_Class_info</code> structure.
696      *
697      * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
698      * for storing the class name.
699      *
700      * @return          the index of the added entry.
701      */
addClassInfo(CtClass c)702     public int addClassInfo(CtClass c) {
703         if (c == THIS)
704             return thisClassInfo;
705         else if (!c.isArray())
706             return addClassInfo(c.getName());
707         else {
708             // an array type is recorded in the hashtable with
709             // the key "[L<classname>;" instead of "<classname>".
710             //
711             // note: toJvmName(toJvmName(c)) is equal to toJvmName(c).
712 
713             return addClassInfo(Descriptor.toJvmName(c));
714         }
715     }
716 
717     /**
718      * Adds a new <code>CONSTANT_Class_info</code> structure.
719      *
720      * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
721      * for storing the class name.
722      *
723      * @param qname     a fully-qualified class name
724      *                  (or the JVM-internal representation of that name).
725      * @return          the index of the added entry.
726      */
addClassInfo(String qname)727     public int addClassInfo(String qname) {
728         ClassInfo info = (ClassInfo)classes.get(qname);
729         if (info != null)
730             return info.index;
731         else {
732             int utf8 = addUtf8Info(Descriptor.toJvmName(qname));
733             info = new ClassInfo(utf8, numOfItems);
734             classes.put(qname, info);
735             return addItem(info);
736         }
737     }
738 
739     /**
740      * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
741      *
742      * <p>This also adds <code>CONSTANT_Utf8_info</code> structures.
743      *
744      * @param name      <code>name_index</code>
745      * @param type      <code>descriptor_index</code>
746      * @return          the index of the added entry.
747      */
addNameAndTypeInfo(String name, String type)748     public int addNameAndTypeInfo(String name, String type) {
749         return addNameAndTypeInfo(addUtf8Info(name), addUtf8Info(type));
750     }
751 
752     /**
753      * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
754      *
755      * @param name      <code>name_index</code>
756      * @param type      <code>descriptor_index</code>
757      * @return          the index of the added entry.
758      */
addNameAndTypeInfo(int name, int type)759     public int addNameAndTypeInfo(int name, int type) {
760         int h = hashFunc(name, type);
761         ConstInfo ci = constInfoCache[h];
762         if (ci != null && ci instanceof NameAndTypeInfo && ci.hashCheck(name, type))
763             return constInfoIndexCache[h];
764         else {
765             NameAndTypeInfo item = new NameAndTypeInfo(name, type);
766             constInfoCache[h] = item;
767             int i = addItem(item);
768             constInfoIndexCache[h] = i;
769             return i;
770         }
771     }
772 
773     /**
774      * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
775      *
776      * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
777      * structure.
778      *
779      * @param classInfo         <code>class_index</code>
780      * @param name              <code>name_index</code>
781      *                          of <code>CONSTANT_NameAndType_info</code>.
782      * @param type              <code>descriptor_index</code>
783      *                          of <code>CONSTANT_NameAndType_info</code>.
784      * @return          the index of the added entry.
785      */
addFieldrefInfo(int classInfo, String name, String type)786     public int addFieldrefInfo(int classInfo, String name, String type) {
787         int nt = addNameAndTypeInfo(name, type);
788         return addFieldrefInfo(classInfo, nt);
789     }
790 
791     /**
792      * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
793      *
794      * @param classInfo         <code>class_index</code>
795      * @param nameAndTypeInfo   <code>name_and_type_index</code>.
796      * @return          the index of the added entry.
797      */
addFieldrefInfo(int classInfo, int nameAndTypeInfo)798     public int addFieldrefInfo(int classInfo, int nameAndTypeInfo) {
799         int h = hashFunc(classInfo, nameAndTypeInfo);
800         ConstInfo ci = constInfoCache[h];
801         if (ci != null && ci instanceof FieldrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
802             return constInfoIndexCache[h];
803         else {
804             FieldrefInfo item = new FieldrefInfo(classInfo, nameAndTypeInfo);
805             constInfoCache[h] = item;
806             int i = addItem(item);
807             constInfoIndexCache[h] = i;
808             return i;
809         }
810     }
811 
812     /**
813      * Adds a new <code>CONSTANT_Methodref_info</code> structure.
814      *
815      * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
816      * structure.
817      *
818      * @param classInfo         <code>class_index</code>
819      * @param name              <code>name_index</code>
820      *                          of <code>CONSTANT_NameAndType_info</code>.
821      * @param type              <code>descriptor_index</code>
822      *                          of <code>CONSTANT_NameAndType_info</code>.
823      * @return          the index of the added entry.
824      */
addMethodrefInfo(int classInfo, String name, String type)825     public int addMethodrefInfo(int classInfo, String name, String type) {
826         int nt = addNameAndTypeInfo(name, type);
827         return addMethodrefInfo(classInfo, nt);
828     }
829 
830     /**
831      * Adds a new <code>CONSTANT_Methodref_info</code> structure.
832      *
833      * @param classInfo         <code>class_index</code>
834      * @param nameAndTypeInfo   <code>name_and_type_index</code>.
835      * @return          the index of the added entry.
836      */
addMethodrefInfo(int classInfo, int nameAndTypeInfo)837     public int addMethodrefInfo(int classInfo, int nameAndTypeInfo) {
838         int h = hashFunc(classInfo, nameAndTypeInfo);
839         ConstInfo ci = constInfoCache[h];
840         if (ci != null && ci instanceof MethodrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
841             return constInfoIndexCache[h];
842         else {
843             MethodrefInfo item = new MethodrefInfo(classInfo, nameAndTypeInfo);
844             constInfoCache[h] = item;
845             int i = addItem(item);
846             constInfoIndexCache[h] = i;
847             return i;
848         }
849     }
850 
851     /**
852      * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
853      * structure.
854      *
855      * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
856      * structure.
857      *
858      * @param classInfo         <code>class_index</code>
859      * @param name              <code>name_index</code>
860      *                          of <code>CONSTANT_NameAndType_info</code>.
861      * @param type              <code>descriptor_index</code>
862      *                          of <code>CONSTANT_NameAndType_info</code>.
863      * @return          the index of the added entry.
864      */
addInterfaceMethodrefInfo(int classInfo, String name, String type)865     public int addInterfaceMethodrefInfo(int classInfo, String name,
866                                          String type) {
867         int nt = addNameAndTypeInfo(name, type);
868         return addInterfaceMethodrefInfo(classInfo, nt);
869     }
870 
871     /**
872      * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
873      * structure.
874      *
875      * @param classInfo         <code>class_index</code>
876      * @param nameAndTypeInfo   <code>name_and_type_index</code>.
877      * @return          the index of the added entry.
878      */
addInterfaceMethodrefInfo(int classInfo, int nameAndTypeInfo)879     public int addInterfaceMethodrefInfo(int classInfo,
880                                          int nameAndTypeInfo) {
881         int h = hashFunc(classInfo, nameAndTypeInfo);
882         ConstInfo ci = constInfoCache[h];
883         if (ci != null && ci instanceof InterfaceMethodrefInfo && ci.hashCheck(classInfo, nameAndTypeInfo))
884             return constInfoIndexCache[h];
885         else {
886             InterfaceMethodrefInfo item =new InterfaceMethodrefInfo(classInfo, nameAndTypeInfo);
887             constInfoCache[h] = item;
888             int i = addItem(item);
889             constInfoIndexCache[h] = i;
890             return i;
891         }
892     }
893 
894     /**
895      * Adds a new <code>CONSTANT_String_info</code>
896      * structure.
897      *
898      * <p>This also adds a new <code>CONSTANT_Utf8_info</code>
899      * structure.
900      *
901      * @return          the index of the added entry.
902      */
addStringInfo(String str)903     public int addStringInfo(String str) {
904         return addItem(new StringInfo(addUtf8Info(str)));
905     }
906 
907     /**
908      * Adds a new <code>CONSTANT_Integer_info</code>
909      * structure.
910      *
911      * @return          the index of the added entry.
912      */
addIntegerInfo(int i)913     public int addIntegerInfo(int i) {
914         return addItem(new IntegerInfo(i));
915     }
916 
917     /**
918      * Adds a new <code>CONSTANT_Float_info</code>
919      * structure.
920      *
921      * @return          the index of the added entry.
922      */
addFloatInfo(float f)923     public int addFloatInfo(float f) {
924         return addItem(new FloatInfo(f));
925     }
926 
927     /**
928      * Adds a new <code>CONSTANT_Long_info</code>
929      * structure.
930      *
931      * @return          the index of the added entry.
932      */
addLongInfo(long l)933     public int addLongInfo(long l) {
934         int i = addItem(new LongInfo(l));
935         addItem(new ConstInfoPadding());
936         return i;
937     }
938 
939     /**
940      * Adds a new <code>CONSTANT_Double_info</code>
941      * structure.
942      *
943      * @return          the index of the added entry.
944      */
addDoubleInfo(double d)945     public int addDoubleInfo(double d) {
946         int i = addItem(new DoubleInfo(d));
947         addItem(new ConstInfoPadding());
948         return i;
949     }
950 
951     /**
952      * Adds a new <code>CONSTANT_Utf8_info</code>
953      * structure.
954      *
955      * <p>If the given utf8 string has been already recorded in the
956      * table, then this method does not add a new entry to avoid adding
957      * a duplicated entry.
958      * Instead, it returns the index of the entry already recorded.
959      *
960      * @return          the index of the added entry.
961      */
addUtf8Info(String utf8)962     public int addUtf8Info(String utf8) {
963         Utf8Info info = (Utf8Info)strings.get(utf8);
964         if (info != null)
965             return info.index;
966         else {
967             info = new Utf8Info(utf8, numOfItems);
968             strings.put(utf8, info);
969             return addItem(info);
970         }
971     }
972 
973     /**
974      * Get all the class names.
975      *
976      * @return a set of class names
977      */
getClassNames()978     public Set getClassNames()
979     {
980         HashSet result = new HashSet();
981         LongVector v = items;
982         int size = numOfItems;
983         for (int i = 1; i < size; ++i) {
984             String className = v.elementAt(i).getClassName(this);
985             if (className != null)
986                result.add(className);
987         }
988         return result;
989     }
990 
991     /**
992      * Replaces all occurrences of a class name.
993      *
994      * @param oldName           the replaced name (JVM-internal representation).
995      * @param newName           the substituted name (JVM-internal representation).
996      */
renameClass(String oldName, String newName)997     public void renameClass(String oldName, String newName) {
998         LongVector v = items;
999         int size = numOfItems;
1000         classes = new HashMap(classes.size() * 2);
1001         for (int i = 1; i < size; ++i) {
1002             ConstInfo ci = v.elementAt(i);
1003             ci.renameClass(this, oldName, newName);
1004             ci.makeHashtable(this);
1005         }
1006     }
1007 
1008     /**
1009      * Replaces all occurrences of class names.
1010      *
1011      * @param classnames        specifies pairs of replaced and substituted
1012      *                          name.
1013      */
renameClass(Map classnames)1014     public void renameClass(Map classnames) {
1015         LongVector v = items;
1016         int size = numOfItems;
1017         classes = new HashMap(classes.size() * 2);
1018         for (int i = 1; i < size; ++i) {
1019             ConstInfo ci = v.elementAt(i);
1020             ci.renameClass(this, classnames);
1021             ci.makeHashtable(this);
1022         }
1023     }
1024 
read(DataInputStream in)1025     private void read(DataInputStream in) throws IOException {
1026         int n = in.readUnsignedShort();
1027 
1028         items = new LongVector(n);
1029         numOfItems = 0;
1030         addItem(null);          // index 0 is reserved by the JVM.
1031 
1032         while (--n > 0) {       // index 0 is reserved by JVM
1033             int tag = readOne(in);
1034             if ((tag == LongInfo.tag) || (tag == DoubleInfo.tag)) {
1035                 addItem(new ConstInfoPadding());
1036                 --n;
1037             }
1038         }
1039 
1040         int i = 1;
1041         while (true) {
1042             ConstInfo info = items.elementAt(i++);
1043             if (info == null)
1044                 break;
1045             else
1046                 info.makeHashtable(this);
1047         }
1048     }
1049 
readOne(DataInputStream in)1050     private int readOne(DataInputStream in) throws IOException {
1051         ConstInfo info;
1052         int tag = in.readUnsignedByte();
1053         switch (tag) {
1054         case Utf8Info.tag :                     // 1
1055             info = new Utf8Info(in, numOfItems);
1056             strings.put(((Utf8Info)info).string, info);
1057             break;
1058         case IntegerInfo.tag :                  // 3
1059             info = new IntegerInfo(in);
1060             break;
1061         case FloatInfo.tag :                    // 4
1062             info = new FloatInfo(in);
1063             break;
1064         case LongInfo.tag :                     // 5
1065             info = new LongInfo(in);
1066             break;
1067         case DoubleInfo.tag :                   // 6
1068             info = new DoubleInfo(in);
1069             break;
1070         case ClassInfo.tag :                    // 7
1071             info = new ClassInfo(in, numOfItems);
1072             // classes.put(<classname>, info);
1073             break;
1074         case StringInfo.tag :                   // 8
1075             info = new StringInfo(in);
1076             break;
1077         case FieldrefInfo.tag :                 // 9
1078             info = new FieldrefInfo(in);
1079             break;
1080         case MethodrefInfo.tag :                // 10
1081             info = new MethodrefInfo(in);
1082             break;
1083         case InterfaceMethodrefInfo.tag :       // 11
1084             info = new InterfaceMethodrefInfo(in);
1085             break;
1086         case NameAndTypeInfo.tag :              // 12
1087             info = new NameAndTypeInfo(in);
1088             break;
1089         default :
1090             throw new IOException("invalid constant type: " + tag);
1091         }
1092 
1093         addItem(info);
1094         return tag;
1095     }
1096 
1097     /**
1098      * Writes the contents of the constant pool table.
1099      */
write(DataOutputStream out)1100     public void write(DataOutputStream out) throws IOException {
1101         out.writeShort(numOfItems);
1102         LongVector v = items;
1103         int size = numOfItems;
1104         for (int i = 1; i < size; ++i)
1105             v.elementAt(i).write(out);
1106     }
1107 
1108     /**
1109      * Prints the contents of the constant pool table.
1110      */
print()1111     public void print() {
1112         print(new PrintWriter(System.out, true));
1113     }
1114 
1115     /**
1116      * Prints the contents of the constant pool table.
1117      */
print(PrintWriter out)1118     public void print(PrintWriter out) {
1119         int size = numOfItems;
1120         for (int i = 1; i < size; ++i) {
1121             out.print(i);
1122             out.print(" ");
1123             items.elementAt(i).print(out);
1124         }
1125     }
1126 }
1127 
1128 abstract class ConstInfo {
getTag()1129     public abstract int getTag();
1130 
getClassName(ConstPool cp)1131     public String getClassName(ConstPool cp) { return null; }
renameClass(ConstPool cp, String oldName, String newName)1132     public void renameClass(ConstPool cp, String oldName, String newName) {}
renameClass(ConstPool cp, Map classnames)1133     public void renameClass(ConstPool cp, Map classnames) {}
copy(ConstPool src, ConstPool dest, Map classnames)1134     public abstract int copy(ConstPool src, ConstPool dest, Map classnames);
1135                         // ** classnames is a mapping between JVM names.
1136 
write(DataOutputStream out)1137     public abstract void write(DataOutputStream out) throws IOException;
print(PrintWriter out)1138     public abstract void print(PrintWriter out);
1139 
makeHashtable(ConstPool cp)1140     void makeHashtable(ConstPool cp) {}     // called after read() finishes in ConstPool.
1141 
hashCheck(int a, int b)1142     boolean hashCheck(int a, int b) { return false; }
1143 
toString()1144     public String toString() {
1145         ByteArrayOutputStream bout = new ByteArrayOutputStream();
1146         PrintWriter out = new PrintWriter(bout);
1147         print(out);
1148         return bout.toString();
1149     }
1150 }
1151 
1152 /* padding following DoubleInfo or LongInfo.
1153  */
1154 class ConstInfoPadding extends ConstInfo {
getTag()1155     public int getTag() { return 0; }
1156 
copy(ConstPool src, ConstPool dest, Map map)1157     public int copy(ConstPool src, ConstPool dest, Map map) {
1158         return dest.addConstInfoPadding();
1159     }
1160 
write(DataOutputStream out)1161     public void write(DataOutputStream out) throws IOException {}
1162 
print(PrintWriter out)1163     public void print(PrintWriter out) {
1164         out.println("padding");
1165     }
1166 }
1167 
1168 class ClassInfo extends ConstInfo {
1169     static final int tag = 7;
1170     int name;
1171     int index;
1172 
ClassInfo(int className, int i)1173     public ClassInfo(int className, int i) {
1174         name = className;
1175         index = i;
1176     }
1177 
ClassInfo(DataInputStream in, int i)1178     public ClassInfo(DataInputStream in, int i) throws IOException {
1179         name = in.readUnsignedShort();
1180         index = i;
1181     }
1182 
getTag()1183     public int getTag() { return tag; }
1184 
getClassName(ConstPool cp)1185     public String getClassName(ConstPool cp) {
1186         return cp.getUtf8Info(name);
1187     };
1188 
renameClass(ConstPool cp, String oldName, String newName)1189     public void renameClass(ConstPool cp, String oldName, String newName) {
1190         String nameStr = cp.getUtf8Info(name);
1191         if (nameStr.equals(oldName))
1192             name = cp.addUtf8Info(newName);
1193         else if (nameStr.charAt(0) == '[') {
1194             String nameStr2 = Descriptor.rename(nameStr, oldName, newName);
1195             if (nameStr != nameStr2)
1196                 name = cp.addUtf8Info(nameStr2);
1197         }
1198     }
1199 
renameClass(ConstPool cp, Map map)1200     public void renameClass(ConstPool cp, Map map) {
1201         String oldName = cp.getUtf8Info(name);
1202         if (oldName.charAt(0) == '[') {
1203             String newName = Descriptor.rename(oldName, map);
1204             if (oldName != newName)
1205                 name = cp.addUtf8Info(newName);
1206         }
1207         else {
1208             String newName = (String)map.get(oldName);
1209             if (newName != null && !newName.equals(oldName))
1210                 name = cp.addUtf8Info(newName);
1211         }
1212     }
1213 
copy(ConstPool src, ConstPool dest, Map map)1214     public int copy(ConstPool src, ConstPool dest, Map map) {
1215         String classname = src.getUtf8Info(name);
1216         if (map != null) {
1217             String newname = (String)map.get(classname);
1218             if (newname != null)
1219                 classname = newname;
1220         }
1221 
1222         return dest.addClassInfo(classname);
1223     }
1224 
write(DataOutputStream out)1225     public void write(DataOutputStream out) throws IOException {
1226         out.writeByte(tag);
1227         out.writeShort(name);
1228     }
1229 
print(PrintWriter out)1230     public void print(PrintWriter out) {
1231         out.print("Class #");
1232         out.println(name);
1233     }
1234 
makeHashtable(ConstPool cp)1235     void makeHashtable(ConstPool cp) {
1236         String name = Descriptor.toJavaName(getClassName(cp));
1237         cp.classes.put(name, this);
1238     }
1239 }
1240 
1241 class NameAndTypeInfo extends ConstInfo {
1242     static final int tag = 12;
1243     int memberName;
1244     int typeDescriptor;
1245 
NameAndTypeInfo(int name, int type)1246     public NameAndTypeInfo(int name, int type) {
1247         memberName = name;
1248         typeDescriptor = type;
1249     }
1250 
NameAndTypeInfo(DataInputStream in)1251     public NameAndTypeInfo(DataInputStream in) throws IOException {
1252         memberName = in.readUnsignedShort();
1253         typeDescriptor = in.readUnsignedShort();
1254     }
1255 
hashCheck(int a, int b)1256     boolean hashCheck(int a, int b) { return a == memberName && b == typeDescriptor; }
1257 
getTag()1258     public int getTag() { return tag; }
1259 
renameClass(ConstPool cp, String oldName, String newName)1260     public void renameClass(ConstPool cp, String oldName, String newName) {
1261         String type = cp.getUtf8Info(typeDescriptor);
1262         String type2 = Descriptor.rename(type, oldName, newName);
1263         if (type != type2)
1264             typeDescriptor = cp.addUtf8Info(type2);
1265     }
1266 
renameClass(ConstPool cp, Map map)1267     public void renameClass(ConstPool cp, Map map) {
1268         String type = cp.getUtf8Info(typeDescriptor);
1269         String type2 = Descriptor.rename(type, map);
1270         if (type != type2)
1271             typeDescriptor = cp.addUtf8Info(type2);
1272     }
1273 
copy(ConstPool src, ConstPool dest, Map map)1274     public int copy(ConstPool src, ConstPool dest, Map map) {
1275         String mname = src.getUtf8Info(memberName);
1276         String tdesc = src.getUtf8Info(typeDescriptor);
1277         tdesc = Descriptor.rename(tdesc, map);
1278         return dest.addNameAndTypeInfo(dest.addUtf8Info(mname),
1279                                        dest.addUtf8Info(tdesc));
1280     }
1281 
write(DataOutputStream out)1282     public void write(DataOutputStream out) throws IOException {
1283         out.writeByte(tag);
1284         out.writeShort(memberName);
1285         out.writeShort(typeDescriptor);
1286     }
1287 
print(PrintWriter out)1288     public void print(PrintWriter out) {
1289         out.print("NameAndType #");
1290         out.print(memberName);
1291         out.print(", type #");
1292         out.println(typeDescriptor);
1293     }
1294 }
1295 
1296 abstract class MemberrefInfo extends ConstInfo {
1297     int classIndex;
1298     int nameAndTypeIndex;
1299 
MemberrefInfo(int cindex, int ntindex)1300     public MemberrefInfo(int cindex, int ntindex) {
1301         classIndex = cindex;
1302         nameAndTypeIndex = ntindex;
1303     }
1304 
MemberrefInfo(DataInputStream in)1305     public MemberrefInfo(DataInputStream in) throws IOException {
1306         classIndex = in.readUnsignedShort();
1307         nameAndTypeIndex = in.readUnsignedShort();
1308     }
1309 
copy(ConstPool src, ConstPool dest, Map map)1310     public int copy(ConstPool src, ConstPool dest, Map map) {
1311         int classIndex2 = src.getItem(classIndex).copy(src, dest, map);
1312         int ntIndex2 = src.getItem(nameAndTypeIndex).copy(src, dest, map);
1313         return copy2(dest, classIndex2, ntIndex2);
1314     }
1315 
hashCheck(int a, int b)1316     boolean hashCheck(int a, int b) { return a == classIndex && b == nameAndTypeIndex; }
1317 
copy2(ConstPool dest, int cindex, int ntindex)1318     abstract protected int copy2(ConstPool dest, int cindex, int ntindex);
1319 
write(DataOutputStream out)1320     public void write(DataOutputStream out) throws IOException {
1321         out.writeByte(getTag());
1322         out.writeShort(classIndex);
1323         out.writeShort(nameAndTypeIndex);
1324     }
1325 
print(PrintWriter out)1326     public void print(PrintWriter out) {
1327         out.print(getTagName() + " #");
1328         out.print(classIndex);
1329         out.print(", name&type #");
1330         out.println(nameAndTypeIndex);
1331     }
1332 
getTagName()1333     public abstract String getTagName();
1334 }
1335 
1336 class FieldrefInfo extends MemberrefInfo {
1337     static final int tag = 9;
1338 
FieldrefInfo(int cindex, int ntindex)1339     public FieldrefInfo(int cindex, int ntindex) {
1340         super(cindex, ntindex);
1341     }
1342 
FieldrefInfo(DataInputStream in)1343     public FieldrefInfo(DataInputStream in) throws IOException {
1344         super(in);
1345     }
1346 
getTag()1347     public int getTag() { return tag; }
1348 
getTagName()1349     public String getTagName() { return "Field"; }
1350 
copy2(ConstPool dest, int cindex, int ntindex)1351     protected int copy2(ConstPool dest, int cindex, int ntindex) {
1352         return dest.addFieldrefInfo(cindex, ntindex);
1353     }
1354 }
1355 
1356 class MethodrefInfo extends MemberrefInfo {
1357     static final int tag = 10;
1358 
MethodrefInfo(int cindex, int ntindex)1359     public MethodrefInfo(int cindex, int ntindex) {
1360         super(cindex, ntindex);
1361     }
1362 
MethodrefInfo(DataInputStream in)1363     public MethodrefInfo(DataInputStream in) throws IOException {
1364         super(in);
1365     }
1366 
getTag()1367     public int getTag() { return tag; }
1368 
getTagName()1369     public String getTagName() { return "Method"; }
1370 
copy2(ConstPool dest, int cindex, int ntindex)1371     protected int copy2(ConstPool dest, int cindex, int ntindex) {
1372         return dest.addMethodrefInfo(cindex, ntindex);
1373     }
1374 }
1375 
1376 class InterfaceMethodrefInfo extends MemberrefInfo {
1377     static final int tag = 11;
1378 
InterfaceMethodrefInfo(int cindex, int ntindex)1379     public InterfaceMethodrefInfo(int cindex, int ntindex) {
1380         super(cindex, ntindex);
1381     }
1382 
InterfaceMethodrefInfo(DataInputStream in)1383     public InterfaceMethodrefInfo(DataInputStream in) throws IOException {
1384         super(in);
1385     }
1386 
getTag()1387     public int getTag() { return tag; }
1388 
getTagName()1389     public String getTagName() { return "Interface"; }
1390 
copy2(ConstPool dest, int cindex, int ntindex)1391     protected int copy2(ConstPool dest, int cindex, int ntindex) {
1392         return dest.addInterfaceMethodrefInfo(cindex, ntindex);
1393     }
1394 }
1395 
1396 class StringInfo extends ConstInfo {
1397     static final int tag = 8;
1398     int string;
1399 
StringInfo(int str)1400     public StringInfo(int str) {
1401         string = str;
1402     }
1403 
StringInfo(DataInputStream in)1404     public StringInfo(DataInputStream in) throws IOException {
1405         string = in.readUnsignedShort();
1406     }
1407 
getTag()1408     public int getTag() { return tag; }
1409 
copy(ConstPool src, ConstPool dest, Map map)1410     public int copy(ConstPool src, ConstPool dest, Map map) {
1411         return dest.addStringInfo(src.getUtf8Info(string));
1412     }
1413 
write(DataOutputStream out)1414     public void write(DataOutputStream out) throws IOException {
1415         out.writeByte(tag);
1416         out.writeShort(string);
1417     }
1418 
print(PrintWriter out)1419     public void print(PrintWriter out) {
1420         out.print("String #");
1421         out.println(string);
1422     }
1423 }
1424 
1425 class IntegerInfo extends ConstInfo {
1426     static final int tag = 3;
1427     int value;
1428 
IntegerInfo(int i)1429     public IntegerInfo(int i) {
1430         value = i;
1431     }
1432 
IntegerInfo(DataInputStream in)1433     public IntegerInfo(DataInputStream in) throws IOException {
1434         value = in.readInt();
1435     }
1436 
getTag()1437     public int getTag() { return tag; }
1438 
copy(ConstPool src, ConstPool dest, Map map)1439     public int copy(ConstPool src, ConstPool dest, Map map) {
1440         return dest.addIntegerInfo(value);
1441     }
1442 
write(DataOutputStream out)1443     public void write(DataOutputStream out) throws IOException {
1444         out.writeByte(tag);
1445         out.writeInt(value);
1446     }
1447 
print(PrintWriter out)1448     public void print(PrintWriter out) {
1449         out.print("Integer ");
1450         out.println(value);
1451     }
1452 }
1453 
1454 class FloatInfo extends ConstInfo {
1455     static final int tag = 4;
1456     float value;
1457 
FloatInfo(float f)1458     public FloatInfo(float f) {
1459         value = f;
1460     }
1461 
FloatInfo(DataInputStream in)1462     public FloatInfo(DataInputStream in) throws IOException {
1463         value = in.readFloat();
1464     }
1465 
getTag()1466     public int getTag() { return tag; }
1467 
copy(ConstPool src, ConstPool dest, Map map)1468     public int copy(ConstPool src, ConstPool dest, Map map) {
1469         return dest.addFloatInfo(value);
1470     }
1471 
write(DataOutputStream out)1472     public void write(DataOutputStream out) throws IOException {
1473         out.writeByte(tag);
1474         out.writeFloat(value);
1475     }
1476 
print(PrintWriter out)1477     public void print(PrintWriter out) {
1478         out.print("Float ");
1479         out.println(value);
1480     }
1481 }
1482 
1483 class LongInfo extends ConstInfo {
1484     static final int tag = 5;
1485     long value;
1486 
LongInfo(long l)1487     public LongInfo(long l) {
1488         value = l;
1489     }
1490 
LongInfo(DataInputStream in)1491     public LongInfo(DataInputStream in) throws IOException {
1492         value = in.readLong();
1493     }
1494 
getTag()1495     public int getTag() { return tag; }
1496 
copy(ConstPool src, ConstPool dest, Map map)1497     public int copy(ConstPool src, ConstPool dest, Map map) {
1498         return dest.addLongInfo(value);
1499     }
1500 
write(DataOutputStream out)1501     public void write(DataOutputStream out) throws IOException {
1502         out.writeByte(tag);
1503         out.writeLong(value);
1504     }
1505 
print(PrintWriter out)1506     public void print(PrintWriter out) {
1507         out.print("Long ");
1508         out.println(value);
1509     }
1510 }
1511 
1512 class DoubleInfo extends ConstInfo {
1513     static final int tag = 6;
1514     double value;
1515 
DoubleInfo(double d)1516     public DoubleInfo(double d) {
1517         value = d;
1518     }
1519 
DoubleInfo(DataInputStream in)1520     public DoubleInfo(DataInputStream in) throws IOException {
1521         value = in.readDouble();
1522     }
1523 
getTag()1524     public int getTag() { return tag; }
1525 
copy(ConstPool src, ConstPool dest, Map map)1526     public int copy(ConstPool src, ConstPool dest, Map map) {
1527         return dest.addDoubleInfo(value);
1528     }
1529 
write(DataOutputStream out)1530     public void write(DataOutputStream out) throws IOException {
1531         out.writeByte(tag);
1532         out.writeDouble(value);
1533     }
1534 
print(PrintWriter out)1535     public void print(PrintWriter out) {
1536         out.print("Double ");
1537         out.println(value);
1538     }
1539 }
1540 
1541 class Utf8Info extends ConstInfo {
1542     static final int tag = 1;
1543     String string;
1544     int index;
1545 
Utf8Info(String utf8, int i)1546     public Utf8Info(String utf8, int i) {
1547         string = utf8;
1548         index = i;
1549     }
1550 
Utf8Info(DataInputStream in, int i)1551     public Utf8Info(DataInputStream in, int i) throws IOException {
1552         string = in.readUTF();
1553         index = i;
1554     }
1555 
getTag()1556     public int getTag() { return tag; }
1557 
copy(ConstPool src, ConstPool dest, Map map)1558     public int copy(ConstPool src, ConstPool dest, Map map) {
1559         return dest.addUtf8Info(string);
1560     }
1561 
write(DataOutputStream out)1562     public void write(DataOutputStream out) throws IOException {
1563         out.writeByte(tag);
1564         out.writeUTF(string);
1565     }
1566 
print(PrintWriter out)1567     public void print(PrintWriter out) {
1568         out.print("UTF8 \"");
1569         out.print(string);
1570         out.println("\"");
1571     }
1572 }
1573