• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999- 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  * or the Apache License Version 2.0.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  */
16 
17 package javassist.bytecode;
18 
19 import java.io.ByteArrayOutputStream;
20 import java.io.DataInputStream;
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23 import java.io.PrintWriter;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Map;
27 import java.util.Set;
28 
29 import javassist.CtClass;
30 
31 /**
32  * Constant pool table.
33  */
34 public final class ConstPool
35 {
36     LongVector items;
37     int numOfItems;
38     int thisClassInfo;
39     Map<ConstInfo,ConstInfo> itemsCache;
40 
41     /**
42      * <code>CONSTANT_Class</code>
43      */
44     public static final int CONST_Class = ClassInfo.tag;
45 
46     /**
47      * <code>CONSTANT_Fieldref</code>
48      */
49     public static final int CONST_Fieldref = FieldrefInfo.tag;
50 
51     /**
52      * <code>CONSTANT_Methodref</code>
53      */
54     public static final int CONST_Methodref = MethodrefInfo.tag;
55 
56     /**
57      * <code>CONSTANT_InterfaceMethodref</code>
58      */
59     public static final int CONST_InterfaceMethodref
60                                         = InterfaceMethodrefInfo.tag;
61 
62     /**
63      * <code>CONSTANT_String</code>
64      */
65     public static final int CONST_String = StringInfo.tag;
66 
67     /**
68      * <code>CONSTANT_Integer</code>
69      */
70     public static final int CONST_Integer = IntegerInfo.tag;
71 
72     /**
73      * <code>CONSTANT_Float</code>
74      */
75     public static final int CONST_Float = FloatInfo.tag;
76 
77     /**
78      * <code>CONSTANT_Long</code>
79      */
80     public static final int CONST_Long = LongInfo.tag;
81 
82     /**
83      * <code>CONSTANT_Double</code>
84      */
85     public static final int CONST_Double = DoubleInfo.tag;
86 
87     /**
88      * <code>CONSTANT_NameAndType</code>
89      */
90     public static final int CONST_NameAndType = NameAndTypeInfo.tag;
91 
92     /**
93      * <code>CONSTANT_Utf8</code>
94      */
95     public static final int CONST_Utf8 = Utf8Info.tag;
96 
97     /**
98      * <code>CONSTANT_MethodHandle</code>
99      */
100     public static final int CONST_MethodHandle = MethodHandleInfo.tag;
101 
102     /**
103      * <code>CONSTANT_MethodHandle</code>
104      */
105     public static final int CONST_MethodType = MethodTypeInfo.tag;
106 
107     /**
108      * <code>CONSTANT_MethodHandle</code>
109      */
110     public static final int CONST_InvokeDynamic = InvokeDynamicInfo.tag;
111 
112     /**
113      * <code>CONSTANT_Module</code>
114      */
115     public static final int CONST_Module = ModuleInfo.tag;
116 
117     /**
118      * <code>CONSTANT_Package</code>
119      */
120     public static final int CONST_Package = PackageInfo.tag;
121 
122     /**
123      * Represents the class using this constant pool table.
124      */
125     public static final CtClass THIS = null;
126 
127     /**
128      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
129      */
130     public static final int REF_getField = 1;
131 
132     /**
133      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
134      */
135     public static final int REF_getStatic = 2;
136 
137     /**
138      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
139      */
140     public static final int REF_putField = 3;
141 
142     /**
143      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
144      */
145     public static final int REF_putStatic = 4;
146 
147     /**
148      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
149      */
150     public static final int REF_invokeVirtual = 5;
151 
152     /**
153      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
154      */
155     public static final int REF_invokeStatic = 6;
156 
157     /**
158      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
159      */
160     public static final int REF_invokeSpecial = 7;
161 
162     /**
163      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
164      */
165     public static final int REF_newInvokeSpecial = 8;
166 
167     /**
168      * <code>reference_kind</code> of <code>CONSTANT_MethodHandle_info</code>.
169      */
170     public static final int REF_invokeInterface = 9;
171 
172     /**
173      * Constructs a constant pool table.
174      *
175      * @param thisclass         the name of the class using this constant
176      *                          pool table
177      */
ConstPool(String thisclass)178     public ConstPool(String thisclass)
179     {
180         items = new LongVector();
181         itemsCache = null;
182         numOfItems = 0;
183         addItem0(null);          // index 0 is reserved by the JVM.
184         thisClassInfo = addClassInfo(thisclass);
185     }
186 
187     /**
188      * Constructs a constant pool table from the given byte stream.
189      *
190      * @param in        byte stream.
191      */
ConstPool(DataInputStream in)192     public ConstPool(DataInputStream in) throws IOException
193     {
194         itemsCache = null;
195         thisClassInfo = 0;
196         /* read() initializes items and numOfItems, and do addItem(null).
197          */
198         read(in);
199     }
200 
prune()201     void prune()
202     {
203         itemsCache = null;
204     }
205 
206     /**
207      * Returns the number of entries in this table.
208      */
getSize()209     public int getSize()
210     {
211         return numOfItems;
212     }
213 
214     /**
215      * Returns the name of the class using this constant pool table.
216      */
getClassName()217     public String getClassName()
218     {
219         return getClassInfo(thisClassInfo);
220     }
221 
222     /**
223      * Returns the index of <code>CONSTANT_Class_info</code> structure
224      * specifying the class using this constant pool table.
225      */
getThisClassInfo()226     public int getThisClassInfo()
227     {
228         return thisClassInfo;
229     }
230 
setThisClassInfo(int i)231     void setThisClassInfo(int i)
232     {
233         thisClassInfo = i;
234     }
235 
getItem(int n)236     ConstInfo getItem(int n)
237     {
238         return items.elementAt(n);
239     }
240 
241     /**
242      * Returns the <code>tag</code> field of the constant pool table
243      * entry at the given index.
244      *
245      * @return either <code>CONST_Class</code>, <code>CONST_Fieldref</code>,
246      *         <code>CONST_Methodref</code>, or ...
247      */
getTag(int index)248     public int getTag(int index)
249     {
250         return getItem(index).getTag();
251     }
252 
253     /**
254      * Reads <code>CONSTANT_Class_info</code> structure
255      * at the given index.
256      *
257      * @return  a fully-qualified class or interface name specified
258      *          by <code>name_index</code>.  If the type is an array
259      *          type, this method returns an encoded name like
260      *          <code>[Ljava.lang.Object;</code> (note that the separators
261      *          are not slashes but dots).
262      * @see javassist.ClassPool#getCtClass(String)
263      */
getClassInfo(int index)264     public String getClassInfo(int index)
265     {
266         ClassInfo c = (ClassInfo)getItem(index);
267         if (c == null)
268             return null;
269         return Descriptor.toJavaName(getUtf8Info(c.name));
270     }
271 
272     /**
273      * Reads <code>CONSTANT_Class_info</code> structure
274      * at the given index.
275      *
276      * @return  the descriptor of the type specified
277      *          by <code>name_index</code>.
278      * @see javassist.ClassPool#getCtClass(String)
279      * @since 3.15
280      */
getClassInfoByDescriptor(int index)281     public String getClassInfoByDescriptor(int index)
282     {
283         ClassInfo c = (ClassInfo)getItem(index);
284         if (c == null)
285             return null;
286         String className = getUtf8Info(c.name);
287         if (className.charAt(0) == '[')
288             return className;
289         return Descriptor.of(className);
290     }
291 
292     /**
293      * Reads the <code>name_index</code> field of the
294      * <code>CONSTANT_NameAndType_info</code> structure
295      * at the given index.
296      */
getNameAndTypeName(int index)297     public int getNameAndTypeName(int index)
298     {
299         NameAndTypeInfo ntinfo = (NameAndTypeInfo)getItem(index);
300         return ntinfo.memberName;
301     }
302 
303     /**
304      * Reads the <code>descriptor_index</code> field of the
305      * <code>CONSTANT_NameAndType_info</code> structure
306      * at the given index.
307      */
getNameAndTypeDescriptor(int index)308     public int getNameAndTypeDescriptor(int index)
309     {
310         NameAndTypeInfo ntinfo = (NameAndTypeInfo)getItem(index);
311         return ntinfo.typeDescriptor;
312     }
313 
314     /**
315      * Reads the <code>class_index</code> field of the
316      * <code>CONSTANT_Fieldref_info</code>,
317      * <code>CONSTANT_Methodref_info</code>,
318      * or <code>CONSTANT_Interfaceref_info</code>,
319      * structure at the given index.
320      *
321      * @since 3.6
322      */
getMemberClass(int index)323     public int getMemberClass(int index)
324     {
325         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
326         return minfo.classIndex;
327     }
328 
329     /**
330      * Reads the <code>name_and_type_index</code> field of the
331      * <code>CONSTANT_Fieldref_info</code>,
332      * <code>CONSTANT_Methodref_info</code>,
333      * or <code>CONSTANT_Interfaceref_info</code>,
334      * structure at the given index.
335      *
336      * @since 3.6
337      */
getMemberNameAndType(int index)338     public int getMemberNameAndType(int index)
339     {
340         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
341         return minfo.nameAndTypeIndex;
342     }
343 
344     /**
345      * Reads the <code>class_index</code> field of the
346      * <code>CONSTANT_Fieldref_info</code> structure
347      * at the given index.
348      */
getFieldrefClass(int index)349     public int getFieldrefClass(int index)
350     {
351         FieldrefInfo finfo = (FieldrefInfo)getItem(index);
352         return finfo.classIndex;
353     }
354 
355     /**
356      * Reads the <code>class_index</code> field of the
357      * <code>CONSTANT_Fieldref_info</code> structure
358      * at the given index.
359      *
360      * @return the name of the class at that <code>class_index</code>.
361      */
getFieldrefClassName(int index)362     public String getFieldrefClassName(int index)
363     {
364         FieldrefInfo f = (FieldrefInfo)getItem(index);
365         if (f == null)
366             return null;
367         return getClassInfo(f.classIndex);
368     }
369 
370     /**
371      * Reads the <code>name_and_type_index</code> field of the
372      * <code>CONSTANT_Fieldref_info</code> structure
373      * at the given index.
374      */
getFieldrefNameAndType(int index)375     public int getFieldrefNameAndType(int index)
376     {
377         FieldrefInfo finfo = (FieldrefInfo)getItem(index);
378         return finfo.nameAndTypeIndex;
379     }
380 
381     /**
382      * Reads the <code>name_index</code> field of the
383      * <code>CONSTANT_NameAndType_info</code> structure
384      * indirectly specified by the given index.
385      *
386      * @param index     an index to a <code>CONSTANT_Fieldref_info</code>.
387      * @return  the name of the field.
388      */
getFieldrefName(int index)389     public String getFieldrefName(int index)
390     {
391         FieldrefInfo f = (FieldrefInfo)getItem(index);
392         if (f == null)
393             return null;
394         NameAndTypeInfo n = (NameAndTypeInfo)getItem(f.nameAndTypeIndex);
395         if(n == null)
396             return null;
397         return getUtf8Info(n.memberName);
398     }
399 
400     /**
401      * Reads the <code>descriptor_index</code> field of the
402      * <code>CONSTANT_NameAndType_info</code> structure
403      * indirectly specified by the given index.
404      *
405      * @param index     an index to a <code>CONSTANT_Fieldref_info</code>.
406      * @return  the type descriptor of the field.
407      */
getFieldrefType(int index)408     public String getFieldrefType(int index)
409     {
410         FieldrefInfo f = (FieldrefInfo)getItem(index);
411         if (f == null)
412             return null;
413         NameAndTypeInfo n = (NameAndTypeInfo)getItem(f.nameAndTypeIndex);
414         if(n == null)
415             return null;
416         return getUtf8Info(n.typeDescriptor);
417     }
418 
419     /**
420      * Reads the <code>class_index</code> field of the
421      * <code>CONSTANT_Methodref_info</code> structure
422      * at the given index.
423      */
getMethodrefClass(int index)424     public int getMethodrefClass(int index)
425     {
426         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
427         return minfo.classIndex;
428     }
429 
430     /**
431      * Reads the <code>class_index</code> field of the
432      * <code>CONSTANT_Methodref_info</code> structure
433      * at the given index.
434      *
435      * @return the name of the class at that <code>class_index</code>.
436      */
getMethodrefClassName(int index)437     public String getMethodrefClassName(int index)
438     {
439         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
440         if (minfo == null)
441             return null;
442         return getClassInfo(minfo.classIndex);
443     }
444 
445     /**
446      * Reads the <code>name_and_type_index</code> field of the
447      * <code>CONSTANT_Methodref_info</code> structure
448      * at the given index.
449      */
getMethodrefNameAndType(int index)450     public int getMethodrefNameAndType(int index)
451     {
452         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
453         return minfo.nameAndTypeIndex;
454     }
455 
456     /**
457      * Reads the <code>name_index</code> field of the
458      * <code>CONSTANT_NameAndType_info</code> structure
459      * indirectly specified by the given index.
460      *
461      * @param index     an index to a <code>CONSTANT_Methodref_info</code>.
462      * @return  the name of the method.
463      */
getMethodrefName(int index)464     public String getMethodrefName(int index)
465     {
466         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
467         if (minfo == null)
468             return null;
469         NameAndTypeInfo n
470             = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
471         if(n == null)
472             return null;
473         return getUtf8Info(n.memberName);
474     }
475 
476     /**
477      * Reads the <code>descriptor_index</code> field of the
478      * <code>CONSTANT_NameAndType_info</code> structure
479      * indirectly specified by the given index.
480      *
481      * @param index     an index to a <code>CONSTANT_Methodref_info</code>.
482      * @return  the descriptor of the method.
483      */
getMethodrefType(int index)484     public String getMethodrefType(int index)
485     {
486         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
487         if (minfo == null)
488             return null;
489         NameAndTypeInfo n
490             = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
491         if(n == null)
492             return null;
493         return getUtf8Info(n.typeDescriptor);
494     }
495 
496     /**
497      * Reads the <code>class_index</code> field of the
498      * <code>CONSTANT_InterfaceMethodref_info</code> structure
499      * at the given index.
500      */
getInterfaceMethodrefClass(int index)501     public int getInterfaceMethodrefClass(int index)
502     {
503         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
504         return minfo.classIndex;
505     }
506 
507     /**
508      * Reads the <code>class_index</code> field of the
509      * <code>CONSTANT_InterfaceMethodref_info</code> structure
510      * at the given index.
511      *
512      * @return the name of the class at that <code>class_index</code>.
513      */
getInterfaceMethodrefClassName(int index)514     public String getInterfaceMethodrefClassName(int index)
515     {
516         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
517         return getClassInfo(minfo.classIndex);
518     }
519 
520     /**
521      * Reads the <code>name_and_type_index</code> field of the
522      * <code>CONSTANT_InterfaceMethodref_info</code> structure
523      * at the given index.
524      */
getInterfaceMethodrefNameAndType(int index)525     public int getInterfaceMethodrefNameAndType(int index)
526     {
527         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
528         return minfo.nameAndTypeIndex;
529     }
530 
531     /**
532      * Reads the <code>name_index</code> field of the
533      * <code>CONSTANT_NameAndType_info</code> structure
534      * indirectly specified by the given index.
535      *
536      * @param index     an index to
537      *                  a <code>CONSTANT_InterfaceMethodref_info</code>.
538      * @return  the name of the method.
539      */
getInterfaceMethodrefName(int index)540     public String getInterfaceMethodrefName(int index)
541     {
542         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
543         if (minfo == null)
544             return null;
545         NameAndTypeInfo n
546             = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
547         if(n == null)
548             return null;
549         return getUtf8Info(n.memberName);
550     }
551 
552     /**
553      * Reads the <code>descriptor_index</code> field of the
554      * <code>CONSTANT_NameAndType_info</code> structure
555      * indirectly specified by the given index.
556      *
557      * @param index     an index to
558      *                  a <code>CONSTANT_InterfaceMethodref_info</code>.
559      * @return  the descriptor of the method.
560      */
getInterfaceMethodrefType(int index)561     public String getInterfaceMethodrefType(int index)
562     {
563         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
564         if (minfo == null)
565             return null;
566         NameAndTypeInfo n
567             = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
568         if(n == null)
569             return null;
570         return getUtf8Info(n.typeDescriptor);
571     }
572     /**
573      * Reads <code>CONSTANT_Integer_info</code>, <code>_Float_info</code>,
574      * <code>_Long_info</code>, <code>_Double_info</code>, or
575      * <code>_String_info</code> structure.
576      * These are used with the LDC instruction.
577      *
578      * @return a <code>String</code> value or a wrapped primitive-type
579      * value.
580      */
getLdcValue(int index)581     public Object getLdcValue(int index)
582     {
583         ConstInfo constInfo = this.getItem(index);
584         Object value = null;
585         if (constInfo instanceof StringInfo)
586             value = this.getStringInfo(index);
587         else if (constInfo instanceof FloatInfo)
588             value = Float.valueOf(getFloatInfo(index));
589         else if (constInfo instanceof IntegerInfo)
590             value = Integer.valueOf(getIntegerInfo(index));
591         else if (constInfo instanceof LongInfo)
592             value = Long.valueOf(getLongInfo(index));
593         else if (constInfo instanceof DoubleInfo)
594             value = Double.valueOf(getDoubleInfo(index));
595 
596         return value;
597     }
598 
599     /**
600      * Reads <code>CONSTANT_Integer_info</code> structure
601      * at the given index.
602      *
603      * @return the value specified by this entry.
604      */
getIntegerInfo(int index)605     public int getIntegerInfo(int index)
606     {
607         IntegerInfo i = (IntegerInfo)getItem(index);
608         return i.value;
609     }
610 
611     /**
612      * Reads <code>CONSTANT_Float_info</code> structure
613      * at the given index.
614      *
615      * @return the value specified by this entry.
616      */
getFloatInfo(int index)617     public float getFloatInfo(int index)
618     {
619         FloatInfo i = (FloatInfo)getItem(index);
620         return i.value;
621     }
622 
623     /**
624      * Reads <code>CONSTANT_Long_info</code> structure
625      * at the given index.
626      *
627      * @return the value specified by this entry.
628      */
getLongInfo(int index)629     public long getLongInfo(int index)
630     {
631         LongInfo i = (LongInfo)getItem(index);
632         return i.value;
633     }
634 
635     /**
636      * Reads <code>CONSTANT_Double_info</code> structure
637      * at the given index.
638      *
639      * @return the value specified by this entry.
640      */
getDoubleInfo(int index)641     public double getDoubleInfo(int index)
642     {
643         DoubleInfo i = (DoubleInfo)getItem(index);
644         return i.value;
645     }
646 
647     /**
648      * Reads <code>CONSTANT_String_info</code> structure
649      * at the given index.
650      *
651      * @return the string specified by <code>string_index</code>.
652      */
getStringInfo(int index)653     public String getStringInfo(int index)
654     {
655         StringInfo si = (StringInfo)getItem(index);
656         return getUtf8Info(si.string);
657     }
658 
659     /**
660      * Reads <code>CONSTANT_utf8_info</code> structure
661      * at the given index.
662      *
663      * @return the string specified by this entry.
664      */
getUtf8Info(int index)665     public String getUtf8Info(int index)
666     {
667         Utf8Info utf = (Utf8Info)getItem(index);
668         return utf.string;
669     }
670 
671     /**
672      * Reads the <code>reference_kind</code> field of the
673      * <code>CONSTANT_MethodHandle_info</code> structure
674      * at the given index.
675      *
676      * @see #REF_getField
677      * @see #REF_getStatic
678      * @see #REF_invokeInterface
679      * @see #REF_invokeSpecial
680      * @see #REF_invokeStatic
681      * @see #REF_invokeVirtual
682      * @see #REF_newInvokeSpecial
683      * @see #REF_putField
684      * @see #REF_putStatic
685      * @since 3.17
686      */
getMethodHandleKind(int index)687     public int getMethodHandleKind(int index)
688     {
689         MethodHandleInfo mhinfo = (MethodHandleInfo)getItem(index);
690         return mhinfo.refKind;
691     }
692 
693     /**
694      * Reads the <code>reference_index</code> field of the
695      * <code>CONSTANT_MethodHandle_info</code> structure
696      * at the given index.
697      *
698      * @since 3.17
699      */
getMethodHandleIndex(int index)700     public int getMethodHandleIndex(int index)
701     {
702         MethodHandleInfo mhinfo = (MethodHandleInfo)getItem(index);
703         return mhinfo.refIndex;
704     }
705 
706     /**
707      * Reads the <code>descriptor_index</code> field of the
708      * <code>CONSTANT_MethodType_info</code> structure
709      * at the given index.
710      *
711      * @since 3.17
712      */
getMethodTypeInfo(int index)713     public int getMethodTypeInfo(int index)
714     {
715         MethodTypeInfo mtinfo = (MethodTypeInfo)getItem(index);
716         return mtinfo.descriptor;
717     }
718 
719     /**
720      * Reads the <code>bootstrap_method_attr_index</code> field of the
721      * <code>CONSTANT_InvokeDynamic_info</code> structure
722      * at the given index.
723      *
724      * @since 3.17
725      */
getInvokeDynamicBootstrap(int index)726     public int getInvokeDynamicBootstrap(int index)
727     {
728         InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
729         return iv.bootstrap;
730     }
731 
732     /**
733      * Reads the <code>name_and_type_index</code> field of the
734      * <code>CONSTANT_InvokeDynamic_info</code> structure
735      * at the given index.
736      *
737      * @since 3.17
738      */
getInvokeDynamicNameAndType(int index)739     public int getInvokeDynamicNameAndType(int index)
740     {
741         InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
742         return iv.nameAndType;
743     }
744 
745     /**
746      * Reads the <code>descriptor_index</code> field of the
747      * <code>CONSTANT_NameAndType_info</code> structure
748      * indirectly specified by the given index.
749      *
750      * @param index     an index to a <code>CONSTANT_InvokeDynamic_info</code>.
751      * @return  the descriptor of the method.
752      * @since 3.17
753      */
getInvokeDynamicType(int index)754     public String getInvokeDynamicType(int index)
755     {
756         InvokeDynamicInfo iv = (InvokeDynamicInfo)getItem(index);
757         if (iv == null)
758             return null;
759         NameAndTypeInfo n = (NameAndTypeInfo)getItem(iv.nameAndType);
760         if(n == null)
761             return null;
762         return getUtf8Info(n.typeDescriptor);
763     }
764 
765     /**
766      * Reads the <code>name_index</code> field of the
767      * <code>CONSTANT_Module_info</code> structure at the given index.
768      *
769      * @return the module name at <code>name_index</code>.
770      * @since 3.22
771      */
getModuleInfo(int index)772     public String getModuleInfo(int index)
773     {
774         ModuleInfo mi = (ModuleInfo)getItem(index);
775         return getUtf8Info(mi.name);
776     }
777 
778     /**
779      * Reads the <code>name_index</code> field of the
780      * <code>CONSTANT_Package_info</code> structure at the given index.
781      *
782      * @return the package name at <code>name_index</code>.  It is a slash-
783      * separated name such as com/oracle/net.
784      * @since 3.22
785      */
getPackageInfo(int index)786     public String getPackageInfo(int index)
787     {
788         PackageInfo mi = (PackageInfo)getItem(index);
789         return getUtf8Info(mi.name);
790     }
791 
792     /**
793      * Determines whether <code>CONSTANT_Methodref_info</code>
794      * structure at the given index represents the constructor
795      * of the given class.
796      *
797      * @return          the <code>descriptor_index</code> specifying
798      *                  the type descriptor of the that constructor.
799      *                  If it is not that constructor,
800      *                  <code>isConstructor()</code> returns 0.
801      */
isConstructor(String classname, int index)802     public int isConstructor(String classname, int index)
803     {
804         return isMember(classname, MethodInfo.nameInit, index);
805     }
806 
807     /**
808      * Determines whether <code>CONSTANT_Methodref_info</code>,
809      * <code>CONSTANT_Fieldref_info</code>, or
810      * <code>CONSTANT_InterfaceMethodref_info</code> structure
811      * at the given index represents the member with the specified
812      * name and declaring class.
813      *
814      * @param classname         the class declaring the member
815      * @param membername        the member name
816      * @param index             the index into the constant pool table
817      *
818      * @return          the <code>descriptor_index</code> specifying
819      *                  the type descriptor of that member.
820      *                  If it is not that member,
821      *                  <code>isMember()</code> returns 0.
822      */
isMember(String classname, String membername, int index)823     public int isMember(String classname, String membername, int index)
824     {
825         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
826         if (getClassInfo(minfo.classIndex).equals(classname)) {
827             NameAndTypeInfo ntinfo
828                 = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
829             if (getUtf8Info(ntinfo.memberName).equals(membername))
830                 return ntinfo.typeDescriptor;
831         }
832 
833         return 0;       // false
834     }
835 
836     /**
837      * Determines whether <code>CONSTANT_Methodref_info</code>,
838      * <code>CONSTANT_Fieldref_info</code>, or
839      * <code>CONSTANT_InterfaceMethodref_info</code> structure
840      * at the given index has the name and the descriptor
841      * given as the arguments.
842      *
843      * @param membername        the member name
844      * @param desc              the descriptor of the member.
845      * @param index             the index into the constant pool table
846      *
847      * @return          the name of the target class specified by
848      *                  the <code>..._info</code> structure
849      *                  at <code>index</code>.
850      *                  Otherwise, null if that structure does not
851      *                  match the given member name and descriptor.
852      */
eqMember(String membername, String desc, int index)853     public String eqMember(String membername, String desc, int index)
854     {
855         MemberrefInfo minfo = (MemberrefInfo)getItem(index);
856         NameAndTypeInfo ntinfo
857                 = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex);
858         if (getUtf8Info(ntinfo.memberName).equals(membername)
859             && getUtf8Info(ntinfo.typeDescriptor).equals(desc))
860             return getClassInfo(minfo.classIndex);
861         return null;       // false
862     }
863 
addItem0(ConstInfo info)864     private int addItem0(ConstInfo info)
865     {
866         items.addElement(info);
867         return numOfItems++;
868     }
869 
addItem(ConstInfo info)870     private int addItem(ConstInfo info)
871     {
872         if (itemsCache == null)
873             itemsCache = makeItemsCache(items);
874 
875         ConstInfo found = itemsCache.get(info);
876         if (found != null)
877             return found.index;
878         items.addElement(info);
879         itemsCache.put(info, info);
880         return numOfItems++;
881     }
882 
883     /**
884      * Copies the n-th item in this ConstPool object into the destination
885      * ConstPool object.
886      * The class names that the item refers to are renamed according
887      * to the given map.
888      *
889      * @param n                 the <i>n</i>-th item
890      * @param dest              destination constant pool table
891      * @param classnames        the map or null.
892      * @return the index of the copied item into the destination ClassPool.
893      */
copy(int n, ConstPool dest, Map<String,String> classnames)894     public int copy(int n, ConstPool dest, Map<String,String> classnames)
895     {
896         if (n == 0)
897             return 0;
898 
899         ConstInfo info = getItem(n);
900         return info.copy(this, dest, classnames);
901     }
902 
addConstInfoPadding()903     int addConstInfoPadding() {
904         return addItem0(new ConstInfoPadding(numOfItems));
905     }
906 
907     /**
908      * Adds a new <code>CONSTANT_Class_info</code> structure.
909      *
910      * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
911      * for storing the class name.
912      *
913      * @return          the index of the added entry.
914      */
addClassInfo(CtClass c)915     public int addClassInfo(CtClass c)
916     {
917         if (c == THIS)
918             return thisClassInfo;
919         else if (!c.isArray())
920             return addClassInfo(c.getName());
921         else {
922             // an array type is recorded in the hashtable with
923             // the key "[L<classname>;" instead of "<classname>".
924             //
925             // note: toJvmName(toJvmName(c)) is equal to toJvmName(c).
926 
927             return addClassInfo(Descriptor.toJvmName(c));
928         }
929     }
930 
931     /**
932      * Adds a new <code>CONSTANT_Class_info</code> structure.
933      *
934      * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
935      * for storing the class name.
936      *
937      * @param qname     a fully-qualified class name
938      *                  (or the JVM-internal representation of that name).
939      * @return          the index of the added entry.
940      */
addClassInfo(String qname)941     public int addClassInfo(String qname)
942     {
943         int utf8 = addUtf8Info(Descriptor.toJvmName(qname));
944         return addItem(new ClassInfo(utf8, numOfItems));
945     }
946 
947     /**
948      * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
949      *
950      * <p>This also adds <code>CONSTANT_Utf8_info</code> structures.
951      *
952      * @param name      <code>name_index</code>
953      * @param type      <code>descriptor_index</code>
954      * @return          the index of the added entry.
955      */
addNameAndTypeInfo(String name, String type)956     public int addNameAndTypeInfo(String name, String type)
957     {
958         return addNameAndTypeInfo(addUtf8Info(name), addUtf8Info(type));
959     }
960 
961     /**
962      * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
963      *
964      * @param name      <code>name_index</code>
965      * @param type      <code>descriptor_index</code>
966      * @return          the index of the added entry.
967      */
addNameAndTypeInfo(int name, int type)968     public int addNameAndTypeInfo(int name, int type)
969     {
970         return addItem(new NameAndTypeInfo(name, type, numOfItems));
971     }
972 
973     /**
974      * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
975      *
976      * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
977      * structure.
978      *
979      * @param classInfo         <code>class_index</code>
980      * @param name              <code>name_index</code>
981      *                          of <code>CONSTANT_NameAndType_info</code>.
982      * @param type              <code>descriptor_index</code>
983      *                          of <code>CONSTANT_NameAndType_info</code>.
984      * @return          the index of the added entry.
985      */
addFieldrefInfo(int classInfo, String name, String type)986     public int addFieldrefInfo(int classInfo, String name, String type)
987     {
988         int nt = addNameAndTypeInfo(name, type);
989         return addFieldrefInfo(classInfo, nt);
990     }
991 
992     /**
993      * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
994      *
995      * @param classInfo         <code>class_index</code>
996      * @param nameAndTypeInfo   <code>name_and_type_index</code>.
997      * @return          the index of the added entry.
998      */
addFieldrefInfo(int classInfo, int nameAndTypeInfo)999     public int addFieldrefInfo(int classInfo, int nameAndTypeInfo)
1000     {
1001         return addItem(new FieldrefInfo(classInfo, nameAndTypeInfo,
1002                                         numOfItems));
1003     }
1004 
1005     /**
1006      * Adds a new <code>CONSTANT_Methodref_info</code> structure.
1007      *
1008      * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
1009      * structure.
1010      *
1011      * @param classInfo         <code>class_index</code>
1012      * @param name              <code>name_index</code>
1013      *                          of <code>CONSTANT_NameAndType_info</code>.
1014      * @param type              <code>descriptor_index</code>
1015      *                          of <code>CONSTANT_NameAndType_info</code>.
1016      * @return          the index of the added entry.
1017      */
addMethodrefInfo(int classInfo, String name, String type)1018     public int addMethodrefInfo(int classInfo, String name, String type)
1019     {
1020         int nt = addNameAndTypeInfo(name, type);
1021         return addMethodrefInfo(classInfo, nt);
1022     }
1023 
1024     /**
1025      * Adds a new <code>CONSTANT_Methodref_info</code> structure.
1026      *
1027      * @param classInfo         <code>class_index</code>
1028      * @param nameAndTypeInfo   <code>name_and_type_index</code>.
1029      * @return          the index of the added entry.
1030      */
addMethodrefInfo(int classInfo, int nameAndTypeInfo)1031     public int addMethodrefInfo(int classInfo, int nameAndTypeInfo)
1032     {
1033          return addItem(new MethodrefInfo(classInfo,
1034                  nameAndTypeInfo, numOfItems));
1035     }
1036 
1037     /**
1038      * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
1039      * structure.
1040      *
1041      * <p>This also adds a new <code>CONSTANT_NameAndType_info</code>
1042      * structure.
1043      *
1044      * @param classInfo         <code>class_index</code>
1045      * @param name              <code>name_index</code>
1046      *                          of <code>CONSTANT_NameAndType_info</code>.
1047      * @param type              <code>descriptor_index</code>
1048      *                          of <code>CONSTANT_NameAndType_info</code>.
1049      * @return          the index of the added entry.
1050      */
addInterfaceMethodrefInfo(int classInfo, String name, String type)1051     public int addInterfaceMethodrefInfo(int classInfo,
1052                                          String name,
1053                                          String type)
1054     {
1055         int nt = addNameAndTypeInfo(name, type);
1056         return addInterfaceMethodrefInfo(classInfo, nt);
1057     }
1058 
1059     /**
1060      * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
1061      * structure.
1062      *
1063      * @param classInfo         <code>class_index</code>
1064      * @param nameAndTypeInfo   <code>name_and_type_index</code>.
1065      * @return          the index of the added entry.
1066      */
addInterfaceMethodrefInfo(int classInfo, int nameAndTypeInfo)1067     public int addInterfaceMethodrefInfo(int classInfo,
1068                                          int nameAndTypeInfo)
1069     {
1070         return addItem(new InterfaceMethodrefInfo(classInfo,
1071                                                   nameAndTypeInfo,
1072                                                   numOfItems));
1073     }
1074 
1075     /**
1076      * Adds a new <code>CONSTANT_String_info</code>
1077      * structure.
1078      *
1079      * <p>This also adds a new <code>CONSTANT_Utf8_info</code>
1080      * structure.
1081      *
1082      * @return          the index of the added entry.
1083      */
addStringInfo(String str)1084     public int addStringInfo(String str)
1085     {
1086         int utf = addUtf8Info(str);
1087         return addItem(new StringInfo(utf, numOfItems));
1088     }
1089 
1090     /**
1091      * Adds a new <code>CONSTANT_Integer_info</code>
1092      * structure.
1093      *
1094      * @return          the index of the added entry.
1095      */
addIntegerInfo(int i)1096     public int addIntegerInfo(int i)
1097     {
1098         return addItem(new IntegerInfo(i, numOfItems));
1099     }
1100 
1101     /**
1102      * Adds a new <code>CONSTANT_Float_info</code>
1103      * structure.
1104      *
1105      * @return          the index of the added entry.
1106      */
addFloatInfo(float f)1107     public int addFloatInfo(float f)
1108     {
1109         return addItem(new FloatInfo(f, numOfItems));
1110     }
1111 
1112     /**
1113      * Adds a new <code>CONSTANT_Long_info</code>
1114      * structure.
1115      *
1116      * @return          the index of the added entry.
1117      */
addLongInfo(long l)1118     public int addLongInfo(long l)
1119     {
1120         int i = addItem(new LongInfo(l, numOfItems));
1121         if (i == numOfItems - 1)    // if not existing
1122             addConstInfoPadding();
1123 
1124         return i;
1125     }
1126 
1127     /**
1128      * Adds a new <code>CONSTANT_Double_info</code>
1129      * structure.
1130      *
1131      * @return          the index of the added entry.
1132      */
addDoubleInfo(double d)1133     public int addDoubleInfo(double d)
1134     {
1135         int i = addItem(new DoubleInfo(d, numOfItems));
1136         if (i == numOfItems - 1)    // if not existing
1137             addConstInfoPadding();
1138 
1139         return i;
1140     }
1141 
1142     /**
1143      * Adds a new <code>CONSTANT_Utf8_info</code>
1144      * structure.
1145      *
1146      * @return          the index of the added entry.
1147      */
addUtf8Info(String utf8)1148     public int addUtf8Info(String utf8)
1149     {
1150         return addItem(new Utf8Info(utf8, numOfItems));
1151     }
1152 
1153     /**
1154      * Adds a new <code>CONSTANT_MethodHandle_info</code>
1155      * structure.
1156      *
1157      * @param kind      <code>reference_kind</code>
1158      *                  such as {@link #REF_invokeStatic <code>REF_invokeStatic</code>}.
1159      * @param index     <code>reference_index</code>.
1160      * @return          the index of the added entry.
1161      *
1162      * @since 3.17
1163      */
addMethodHandleInfo(int kind, int index)1164     public int addMethodHandleInfo(int kind, int index)
1165     {
1166         return addItem(new MethodHandleInfo(kind, index, numOfItems));
1167     }
1168 
1169     /**
1170      * Adds a new <code>CONSTANT_MethodType_info</code>
1171      * structure.
1172      *
1173      * @param desc      <code>descriptor_index</code>.
1174      * @return          the index of the added entry.
1175      *
1176      * @since 3.17
1177      */
addMethodTypeInfo(int desc)1178     public int addMethodTypeInfo(int desc)
1179     {
1180         return addItem(new MethodTypeInfo(desc, numOfItems));
1181     }
1182 
1183     /**
1184      * Adds a new <code>CONSTANT_InvokeDynamic_info</code>
1185      * structure.
1186      *
1187      * @param bootstrap     <code>bootstrap_method_attr_index</code>.
1188      * @param nameAndType   <code>name_and_type_index</code>.
1189      * @return          the index of the added entry.
1190      *
1191      * @since 3.17
1192      */
addInvokeDynamicInfo(int bootstrap, int nameAndType)1193     public int addInvokeDynamicInfo(int bootstrap, int nameAndType)
1194     {
1195         return addItem(new InvokeDynamicInfo(bootstrap, nameAndType, numOfItems));
1196     }
1197 
1198     /**
1199      * Adds a new <code>CONSTANT_Module_info</code>
1200      * @param nameIndex         the index of the Utf8 entry.
1201      * @return          the index of the added entry.
1202      * @since 3.22
1203      */
addModuleInfo(int nameIndex)1204     public int addModuleInfo(int nameIndex)
1205     {
1206         return addItem(new ModuleInfo(nameIndex, numOfItems));
1207     }
1208 
1209     /**
1210      * Adds a new <code>CONSTANT_Package_info</code>
1211      * @param nameIndex         the index of the Utf8 entry.
1212      * @return          the index of the added entry.
1213      * @since 3.22
1214      */
addPackageInfo(int nameIndex)1215     public int addPackageInfo(int nameIndex)
1216     {
1217         return addItem(new PackageInfo(nameIndex, numOfItems));
1218     }
1219 
1220     /**
1221      * Get all the class names.
1222      *
1223      * @return a set of class names (<code>String</code> objects).
1224      */
getClassNames()1225     public Set<String> getClassNames()
1226     {
1227         Set<String> result = new HashSet<String>();
1228         LongVector v = items;
1229         int size = numOfItems;
1230         for (int i = 1; i < size; ++i) {
1231             String className = v.elementAt(i).getClassName(this);
1232             if (className != null)
1233                result.add(className);
1234         }
1235         return result;
1236     }
1237 
1238     /**
1239      * Replaces all occurrences of a class name.
1240      *
1241      * @param oldName           the replaced name (JVM-internal representation).
1242      * @param newName           the substituted name (JVM-internal representation).
1243      */
renameClass(String oldName, String newName)1244     public void renameClass(String oldName, String newName)
1245     {
1246         LongVector v = items;
1247         int size = numOfItems;
1248         for (int i = 1; i < size; ++i) {
1249             ConstInfo ci = v.elementAt(i);
1250             ci.renameClass(this, oldName, newName, itemsCache);
1251         }
1252     }
1253 
1254     /**
1255      * Replaces all occurrences of class names.
1256      *
1257      * @param classnames        specifies pairs of replaced and substituted
1258      *                          name.
1259      */
renameClass(Map<String,String> classnames)1260     public void renameClass(Map<String,String> classnames)
1261     {
1262         LongVector v = items;
1263         int size = numOfItems;
1264         for (int i = 1; i < size; ++i) {
1265             ConstInfo ci = v.elementAt(i);
1266             ci.renameClass(this, classnames, itemsCache);
1267         }
1268     }
1269 
read(DataInputStream in)1270     private void read(DataInputStream in) throws IOException
1271     {
1272         int n = in.readUnsignedShort();
1273 
1274         items = new LongVector(n);
1275         numOfItems = 0;
1276         addItem0(null);          // index 0 is reserved by the JVM.
1277 
1278         while (--n > 0) {       // index 0 is reserved by JVM
1279             int tag = readOne(in);
1280             if ((tag == LongInfo.tag) || (tag == DoubleInfo.tag)) {
1281                 addConstInfoPadding();
1282                 --n;
1283             }
1284         }
1285     }
1286 
makeItemsCache(LongVector items)1287     private static Map<ConstInfo,ConstInfo> makeItemsCache(LongVector items)
1288     {
1289         Map<ConstInfo,ConstInfo> cache = new HashMap<ConstInfo,ConstInfo>();
1290         int i = 1;
1291         while (true) {
1292             ConstInfo info = items.elementAt(i++);
1293             if (info == null)
1294                 break;
1295             cache.put(info, info);
1296         }
1297 
1298         return cache;
1299     }
1300 
readOne(DataInputStream in)1301     private int readOne(DataInputStream in) throws IOException
1302     {
1303         ConstInfo info;
1304         int tag = in.readUnsignedByte();
1305         switch (tag) {
1306         case Utf8Info.tag :                     // 1
1307             info = new Utf8Info(in, numOfItems);
1308             break;
1309         case IntegerInfo.tag :                  // 3
1310             info = new IntegerInfo(in, numOfItems);
1311             break;
1312         case FloatInfo.tag :                    // 4
1313             info = new FloatInfo(in, numOfItems);
1314             break;
1315         case LongInfo.tag :                     // 5
1316             info = new LongInfo(in, numOfItems);
1317             break;
1318         case DoubleInfo.tag :                   // 6
1319             info = new DoubleInfo(in, numOfItems);
1320             break;
1321         case ClassInfo.tag :                    // 7
1322             info = new ClassInfo(in, numOfItems);
1323             break;
1324         case StringInfo.tag :                   // 8
1325             info = new StringInfo(in, numOfItems);
1326             break;
1327         case FieldrefInfo.tag :                 // 9
1328             info = new FieldrefInfo(in, numOfItems);
1329             break;
1330         case MethodrefInfo.tag :                // 10
1331             info = new MethodrefInfo(in, numOfItems);
1332             break;
1333         case InterfaceMethodrefInfo.tag :       // 11
1334             info = new InterfaceMethodrefInfo(in, numOfItems);
1335             break;
1336         case NameAndTypeInfo.tag :              // 12
1337             info = new NameAndTypeInfo(in, numOfItems);
1338             break;
1339         case MethodHandleInfo.tag :             // 15
1340             info = new MethodHandleInfo(in, numOfItems);
1341             break;
1342         case MethodTypeInfo.tag :               // 16
1343             info = new MethodTypeInfo(in, numOfItems);
1344             break;
1345         case InvokeDynamicInfo.tag :            // 18
1346             info = new InvokeDynamicInfo(in, numOfItems);
1347             break;
1348         case ModuleInfo.tag :                   // 19
1349             info = new ModuleInfo(in, numOfItems);
1350             break;
1351         case PackageInfo.tag :                  // 20
1352             info = new PackageInfo(in, numOfItems);
1353             break;
1354         default :
1355             throw new IOException("invalid constant type: "
1356                                 + tag + " at " + numOfItems);
1357         }
1358 
1359         addItem0(info);
1360         return tag;
1361     }
1362 
1363     /**
1364      * Writes the contents of the constant pool table.
1365      */
write(DataOutputStream out)1366     public void write(DataOutputStream out) throws IOException
1367     {
1368         out.writeShort(numOfItems);
1369         LongVector v = items;
1370         int size = numOfItems;
1371         for (int i = 1; i < size; ++i)
1372             v.elementAt(i).write(out);
1373     }
1374 
1375     /**
1376      * Prints the contents of the constant pool table.
1377      */
print()1378     public void print()
1379     {
1380         print(new PrintWriter(System.out, true));
1381     }
1382 
1383     /**
1384      * Prints the contents of the constant pool table.
1385      */
print(PrintWriter out)1386     public void print(PrintWriter out)
1387     {
1388         int size = numOfItems;
1389         for (int i = 1; i < size; ++i) {
1390             out.print(i);
1391             out.print(" ");
1392             items.elementAt(i).print(out);
1393         }
1394     }
1395 }
1396 
1397 abstract class ConstInfo
1398 {
1399     int index;
1400 
ConstInfo(int i)1401     public ConstInfo(int i) { index = i; }
1402 
getTag()1403     public abstract int getTag();
1404 
getClassName(ConstPool cp)1405     public String getClassName(ConstPool cp) { return null; }
renameClass(ConstPool cp, String oldName, String newName, Map<ConstInfo,ConstInfo> cache)1406     public void renameClass(ConstPool cp, String oldName, String newName,
1407             Map<ConstInfo,ConstInfo> cache) {}
renameClass(ConstPool cp, Map<String,String> classnames, Map<ConstInfo,ConstInfo> cache)1408     public void renameClass(ConstPool cp, Map<String,String> classnames,
1409             Map<ConstInfo,ConstInfo> cache) {}
copy(ConstPool src, ConstPool dest, Map<String, String> classnames)1410     public abstract int copy(ConstPool src, ConstPool dest,
1411             Map<String, String> classnames);
1412         // ** classnames is a mapping between JVM names.
1413 
write(DataOutputStream out)1414     public abstract void write(DataOutputStream out) throws IOException;
print(PrintWriter out)1415     public abstract void print(PrintWriter out);
1416 
1417     @Override
toString()1418     public String toString() {
1419         ByteArrayOutputStream bout = new ByteArrayOutputStream();
1420         PrintWriter out = new PrintWriter(bout);
1421         print(out);
1422         return bout.toString();
1423     }
1424 }
1425 
1426 /* padding following DoubleInfo or LongInfo.
1427  */
1428 class ConstInfoPadding extends ConstInfo
1429 {
ConstInfoPadding(int i)1430     public ConstInfoPadding(int i) { super(i); }
1431 
1432     @Override
getTag()1433     public int getTag() { return 0; }
1434 
1435     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)1436     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
1437     {
1438         return dest.addConstInfoPadding();
1439     }
1440 
1441     @Override
write(DataOutputStream out)1442     public void write(DataOutputStream out) throws IOException {}
1443 
1444     @Override
print(PrintWriter out)1445     public void print(PrintWriter out)
1446     {
1447         out.println("padding");
1448     }
1449 }
1450 
1451 class ClassInfo extends ConstInfo
1452 {
1453     static final int tag = 7;
1454     int name;
1455 
ClassInfo(int className, int index)1456     public ClassInfo(int className, int index)
1457     {
1458         super(index);
1459         name = className;
1460     }
1461 
ClassInfo(DataInputStream in, int index)1462     public ClassInfo(DataInputStream in, int index) throws IOException
1463     {
1464         super(index);
1465         name = in.readUnsignedShort();
1466     }
1467 
1468     @Override
hashCode()1469     public int hashCode() { return name; }
1470 
1471     @Override
equals(Object obj)1472     public boolean equals(Object obj)
1473     {
1474         return obj instanceof ClassInfo && ((ClassInfo)obj).name == name;
1475     }
1476 
1477     @Override
getTag()1478     public int getTag() { return tag; }
1479 
1480     @Override
getClassName(ConstPool cp)1481     public String getClassName(ConstPool cp)
1482     {
1483         return cp.getUtf8Info(name);
1484     }
1485 
1486     @Override
renameClass(ConstPool cp, String oldName, String newName, Map<ConstInfo,ConstInfo> cache)1487     public void renameClass(ConstPool cp, String oldName, String newName,
1488             Map<ConstInfo,ConstInfo> cache)
1489     {
1490         String nameStr = cp.getUtf8Info(name);
1491         String newNameStr = null;
1492         if (nameStr.equals(oldName))
1493             newNameStr = newName;
1494         else if (nameStr.charAt(0) == '[') {
1495             String s = Descriptor.rename(nameStr, oldName, newName);
1496             if (nameStr != s)
1497                 newNameStr = s;
1498         }
1499 
1500         if (newNameStr != null)
1501             if (cache == null)
1502                 name = cp.addUtf8Info(newNameStr);
1503             else {
1504                 cache.remove(this);
1505                 name = cp.addUtf8Info(newNameStr);
1506                 cache.put(this, this);
1507             }
1508     }
1509 
1510     @Override
renameClass(ConstPool cp, Map<String,String> map, Map<ConstInfo,ConstInfo> cache)1511     public void renameClass(ConstPool cp, Map<String,String> map,
1512             Map<ConstInfo,ConstInfo> cache)
1513     {
1514         String oldName = cp.getUtf8Info(name);
1515         String newName = null;
1516         if (oldName.charAt(0) == '[') {
1517             String s = Descriptor.rename(oldName, map);
1518             if (oldName != s)
1519                 newName = s;
1520         }
1521         else {
1522             String s = map.get(oldName);
1523             if (s != null && !s.equals(oldName))
1524                 newName = s;
1525         }
1526 
1527         if (newName != null) {
1528             if (cache == null)
1529                 name = cp.addUtf8Info(newName);
1530             else {
1531                 cache.remove(this);
1532                 name = cp.addUtf8Info(newName);
1533                 cache.put(this, this);
1534             }
1535         }
1536     }
1537 
1538     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)1539     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
1540     {
1541         String classname = src.getUtf8Info(name);
1542         if (map != null) {
1543             String newname = map.get(classname);
1544             if (newname != null)
1545                 classname = newname;
1546         }
1547 
1548         return dest.addClassInfo(classname);
1549     }
1550 
1551     @Override
write(DataOutputStream out)1552     public void write(DataOutputStream out) throws IOException
1553     {
1554         out.writeByte(tag);
1555         out.writeShort(name);
1556     }
1557 
1558     @Override
print(PrintWriter out)1559     public void print(PrintWriter out)
1560     {
1561         out.print("Class #");
1562         out.println(name);
1563     }
1564 }
1565 
1566 class NameAndTypeInfo extends ConstInfo
1567 {
1568     static final int tag = 12;
1569     int memberName;
1570     int typeDescriptor;
1571 
NameAndTypeInfo(int name, int type, int index)1572     public NameAndTypeInfo(int name, int type, int index)
1573     {
1574         super(index);
1575         memberName = name;
1576         typeDescriptor = type;
1577     }
1578 
NameAndTypeInfo(DataInputStream in, int index)1579     public NameAndTypeInfo(DataInputStream in, int index) throws IOException
1580     {
1581         super(index);
1582         memberName = in.readUnsignedShort();
1583         typeDescriptor = in.readUnsignedShort();
1584     }
1585 
1586     @Override
hashCode()1587     public int hashCode() { return (memberName << 16) ^ typeDescriptor; }
1588 
1589     @Override
equals(Object obj)1590     public boolean equals(Object obj)
1591     {
1592         if (obj instanceof NameAndTypeInfo) {
1593             NameAndTypeInfo nti = (NameAndTypeInfo)obj;
1594             return nti.memberName == memberName
1595                     && nti.typeDescriptor == typeDescriptor;
1596         }
1597         return false;
1598     }
1599 
1600     @Override
getTag()1601     public int getTag() { return tag; }
1602 
1603     @Override
renameClass(ConstPool cp, String oldName, String newName, Map<ConstInfo,ConstInfo> cache)1604     public void renameClass(ConstPool cp, String oldName, String newName,
1605             Map<ConstInfo,ConstInfo> cache)
1606     {
1607         String type = cp.getUtf8Info(typeDescriptor);
1608         String type2 = Descriptor.rename(type, oldName, newName);
1609         if (type != type2)
1610             if (cache == null)
1611                 typeDescriptor = cp.addUtf8Info(type2);
1612             else {
1613                 cache.remove(this);
1614                 typeDescriptor = cp.addUtf8Info(type2);
1615                 cache.put(this, this);
1616             }
1617     }
1618 
1619     @Override
renameClass(ConstPool cp, Map<String,String> map, Map<ConstInfo,ConstInfo> cache)1620     public void renameClass(ConstPool cp, Map<String,String> map,
1621             Map<ConstInfo,ConstInfo> cache)
1622     {
1623         String type = cp.getUtf8Info(typeDescriptor);
1624         String type2 = Descriptor.rename(type, map);
1625         if (type != type2)
1626             if (cache == null)
1627                 typeDescriptor = cp.addUtf8Info(type2);
1628             else {
1629                 cache.remove(this);
1630                 typeDescriptor = cp.addUtf8Info(type2);
1631                 cache.put(this, this);
1632             }
1633     }
1634 
1635     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)1636     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
1637     {
1638         String mname = src.getUtf8Info(memberName);
1639         String tdesc = src.getUtf8Info(typeDescriptor);
1640         tdesc = Descriptor.rename(tdesc, map);
1641         return dest.addNameAndTypeInfo(dest.addUtf8Info(mname),
1642                                        dest.addUtf8Info(tdesc));
1643     }
1644 
1645     @Override
write(DataOutputStream out)1646     public void write(DataOutputStream out) throws IOException {
1647         out.writeByte(tag);
1648         out.writeShort(memberName);
1649         out.writeShort(typeDescriptor);
1650     }
1651 
1652     @Override
print(PrintWriter out)1653     public void print(PrintWriter out) {
1654         out.print("NameAndType #");
1655         out.print(memberName);
1656         out.print(", type #");
1657         out.println(typeDescriptor);
1658     }
1659 }
1660 
1661 abstract class MemberrefInfo extends ConstInfo
1662 {
1663     int classIndex;
1664     int nameAndTypeIndex;
1665 
MemberrefInfo(int cindex, int ntindex, int thisIndex)1666     public MemberrefInfo(int cindex, int ntindex, int thisIndex)
1667     {
1668         super(thisIndex);
1669         classIndex = cindex;
1670         nameAndTypeIndex = ntindex;
1671     }
1672 
MemberrefInfo(DataInputStream in, int thisIndex)1673     public MemberrefInfo(DataInputStream in, int thisIndex)
1674             throws IOException
1675     {
1676         super(thisIndex);
1677         classIndex = in.readUnsignedShort();
1678         nameAndTypeIndex = in.readUnsignedShort();
1679     }
1680 
1681     @Override
hashCode()1682     public int hashCode() { return (classIndex << 16) ^ nameAndTypeIndex; }
1683 
1684     @Override
equals(Object obj)1685     public boolean equals(Object obj) {
1686         if (obj instanceof MemberrefInfo) {
1687             MemberrefInfo mri = (MemberrefInfo)obj;
1688             return mri.classIndex == classIndex
1689                     && mri.nameAndTypeIndex == nameAndTypeIndex
1690                     && mri.getClass() == this.getClass();
1691         }
1692         return false;
1693     }
1694 
1695     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)1696     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
1697     {
1698         int classIndex2 = src.getItem(classIndex).copy(src, dest, map);
1699         int ntIndex2 = src.getItem(nameAndTypeIndex).copy(src, dest, map);
1700         return copy2(dest, classIndex2, ntIndex2);
1701     }
1702 
copy2(ConstPool dest, int cindex, int ntindex)1703     abstract protected int copy2(ConstPool dest, int cindex, int ntindex);
1704 
1705     @Override
write(DataOutputStream out)1706     public void write(DataOutputStream out) throws IOException
1707     {
1708         out.writeByte(getTag());
1709         out.writeShort(classIndex);
1710         out.writeShort(nameAndTypeIndex);
1711     }
1712 
1713     @Override
print(PrintWriter out)1714     public void print(PrintWriter out)
1715     {
1716         out.print(getTagName() + " #");
1717         out.print(classIndex);
1718         out.print(", name&type #");
1719         out.println(nameAndTypeIndex);
1720     }
1721 
getTagName()1722     public abstract String getTagName();
1723 }
1724 
1725 class FieldrefInfo extends MemberrefInfo
1726 {
1727     static final int tag = 9;
1728 
FieldrefInfo(int cindex, int ntindex, int thisIndex)1729     public FieldrefInfo(int cindex, int ntindex, int thisIndex)
1730     {
1731         super(cindex, ntindex, thisIndex);
1732     }
1733 
FieldrefInfo(DataInputStream in, int thisIndex)1734     public FieldrefInfo(DataInputStream in, int thisIndex)
1735             throws IOException
1736     {
1737         super(in, thisIndex);
1738     }
1739 
1740     @Override
getTag()1741     public int getTag() { return tag; }
1742 
1743     @Override
getTagName()1744     public String getTagName() { return "Field"; }
1745 
1746     @Override
copy2(ConstPool dest, int cindex, int ntindex)1747     protected int copy2(ConstPool dest, int cindex, int ntindex)
1748     {
1749         return dest.addFieldrefInfo(cindex, ntindex);
1750     }
1751 }
1752 
1753 class MethodrefInfo extends MemberrefInfo
1754 {
1755     static final int tag = 10;
1756 
MethodrefInfo(int cindex, int ntindex, int thisIndex)1757     public MethodrefInfo(int cindex, int ntindex, int thisIndex)
1758     {
1759         super(cindex, ntindex, thisIndex);
1760     }
1761 
MethodrefInfo(DataInputStream in, int thisIndex)1762     public MethodrefInfo(DataInputStream in, int thisIndex)
1763             throws IOException
1764     {
1765         super(in, thisIndex);
1766     }
1767 
1768     @Override
getTag()1769     public int getTag() { return tag; }
1770 
1771     @Override
getTagName()1772     public String getTagName() { return "Method"; }
1773 
1774     @Override
copy2(ConstPool dest, int cindex, int ntindex)1775     protected int copy2(ConstPool dest, int cindex, int ntindex)
1776     {
1777         return dest.addMethodrefInfo(cindex, ntindex);
1778     }
1779 }
1780 
1781 class InterfaceMethodrefInfo extends MemberrefInfo
1782 {
1783     static final int tag = 11;
1784 
InterfaceMethodrefInfo(int cindex, int ntindex, int thisIndex)1785     public InterfaceMethodrefInfo(int cindex, int ntindex, int thisIndex)
1786     {
1787         super(cindex, ntindex, thisIndex);
1788     }
1789 
InterfaceMethodrefInfo(DataInputStream in, int thisIndex)1790     public InterfaceMethodrefInfo(DataInputStream in, int thisIndex)
1791             throws IOException
1792     {
1793         super(in, thisIndex);
1794     }
1795 
1796     @Override
getTag()1797     public int getTag() { return tag; }
1798 
1799     @Override
getTagName()1800     public String getTagName() { return "Interface"; }
1801 
1802     @Override
copy2(ConstPool dest, int cindex, int ntindex)1803     protected int copy2(ConstPool dest, int cindex, int ntindex)
1804     {
1805         return dest.addInterfaceMethodrefInfo(cindex, ntindex);
1806     }
1807 }
1808 
1809 class StringInfo extends ConstInfo
1810 {
1811     static final int tag = 8;
1812     int string;
1813 
StringInfo(int str, int index)1814     public StringInfo(int str, int index)
1815     {
1816         super(index);
1817         string = str;
1818     }
1819 
StringInfo(DataInputStream in, int index)1820     public StringInfo(DataInputStream in, int index) throws IOException
1821     {
1822         super(index);
1823         string = in.readUnsignedShort();
1824     }
1825 
1826     @Override
hashCode()1827     public int hashCode() { return string; }
1828 
1829     @Override
equals(Object obj)1830     public boolean equals(Object obj)
1831     {
1832         return obj instanceof StringInfo && ((StringInfo)obj).string == string;
1833     }
1834 
1835     @Override
getTag()1836     public int getTag() { return tag; }
1837 
1838     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)1839     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
1840     {
1841         return dest.addStringInfo(src.getUtf8Info(string));
1842     }
1843 
1844     @Override
write(DataOutputStream out)1845     public void write(DataOutputStream out) throws IOException
1846     {
1847         out.writeByte(tag);
1848         out.writeShort(string);
1849     }
1850 
1851     @Override
print(PrintWriter out)1852     public void print(PrintWriter out)
1853     {
1854         out.print("String #");
1855         out.println(string);
1856     }
1857 }
1858 
1859 class IntegerInfo extends ConstInfo
1860 {
1861     static final int tag = 3;
1862     int value;
1863 
IntegerInfo(int v, int index)1864     public IntegerInfo(int v, int index)
1865     {
1866         super(index);
1867         value = v;
1868     }
1869 
IntegerInfo(DataInputStream in, int index)1870     public IntegerInfo(DataInputStream in, int index) throws IOException
1871     {
1872         super(index);
1873         value = in.readInt();
1874     }
1875 
1876     @Override
hashCode()1877     public int hashCode() { return value; }
1878 
1879     @Override
equals(Object obj)1880     public boolean equals(Object obj)
1881     {
1882         return obj instanceof IntegerInfo && ((IntegerInfo)obj).value == value;
1883     }
1884 
1885     @Override
getTag()1886     public int getTag() { return tag; }
1887 
1888     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)1889     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
1890     {
1891         return dest.addIntegerInfo(value);
1892     }
1893 
1894     @Override
write(DataOutputStream out)1895     public void write(DataOutputStream out) throws IOException
1896     {
1897         out.writeByte(tag);
1898         out.writeInt(value);
1899     }
1900 
1901     @Override
print(PrintWriter out)1902     public void print(PrintWriter out)
1903     {
1904         out.print("Integer ");
1905         out.println(value);
1906     }
1907 }
1908 
1909 class FloatInfo extends ConstInfo
1910 {
1911     static final int tag = 4;
1912     float value;
1913 
FloatInfo(float f, int index)1914     public FloatInfo(float f, int index)
1915     {
1916         super(index);
1917         value = f;
1918     }
1919 
FloatInfo(DataInputStream in, int index)1920     public FloatInfo(DataInputStream in, int index) throws IOException
1921     {
1922         super(index);
1923         value = in.readFloat();
1924     }
1925 
1926     @Override
hashCode()1927     public int hashCode() { return Float.floatToIntBits(value); }
1928 
1929     @Override
equals(Object obj)1930     public boolean equals(Object obj)
1931     {
1932         return obj instanceof FloatInfo && ((FloatInfo)obj).value == value;
1933     }
1934 
1935     @Override
getTag()1936     public int getTag() { return tag; }
1937 
1938     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)1939     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
1940     {
1941         return dest.addFloatInfo(value);
1942     }
1943 
1944     @Override
write(DataOutputStream out)1945     public void write(DataOutputStream out) throws IOException
1946     {
1947         out.writeByte(tag);
1948         out.writeFloat(value);
1949     }
1950 
1951     @Override
print(PrintWriter out)1952     public void print(PrintWriter out)
1953     {
1954         out.print("Float ");
1955         out.println(value);
1956     }
1957 }
1958 
1959 class LongInfo extends ConstInfo
1960 {
1961     static final int tag = 5;
1962     long value;
1963 
LongInfo(long l, int index)1964     public LongInfo(long l, int index)
1965     {
1966         super(index);
1967         value = l;
1968     }
1969 
LongInfo(DataInputStream in, int index)1970     public LongInfo(DataInputStream in, int index) throws IOException
1971     {
1972         super(index);
1973         value = in.readLong();
1974     }
1975 
1976     @Override
hashCode()1977     public int hashCode() { return (int)(value ^ (value >>> 32)); }
1978 
1979     @Override
equals(Object obj)1980     public boolean equals(Object obj) {
1981         return obj instanceof LongInfo && ((LongInfo)obj).value == value;
1982     }
1983 
1984     @Override
getTag()1985     public int getTag() { return tag; }
1986 
1987     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)1988     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
1989     {
1990         return dest.addLongInfo(value);
1991     }
1992 
1993     @Override
write(DataOutputStream out)1994     public void write(DataOutputStream out) throws IOException
1995     {
1996         out.writeByte(tag);
1997         out.writeLong(value);
1998     }
1999 
2000     @Override
print(PrintWriter out)2001     public void print(PrintWriter out)
2002     {
2003         out.print("Long ");
2004         out.println(value);
2005     }
2006 }
2007 
2008 class DoubleInfo extends ConstInfo
2009 {
2010     static final int tag = 6;
2011     double value;
2012 
DoubleInfo(double d, int index)2013     public DoubleInfo(double d, int index)
2014     {
2015         super(index);
2016         value = d;
2017     }
2018 
DoubleInfo(DataInputStream in, int index)2019     public DoubleInfo(DataInputStream in, int index) throws IOException
2020     {
2021         super(index);
2022         value = in.readDouble();
2023     }
2024 
2025     @Override
hashCode()2026     public int hashCode() {
2027         long v = Double.doubleToLongBits(value);
2028         return (int)(v ^ (v >>> 32));
2029     }
2030 
2031     @Override
equals(Object obj)2032     public boolean equals(Object obj)
2033     {
2034         return obj instanceof DoubleInfo
2035                 && ((DoubleInfo)obj).value == value;
2036     }
2037 
2038     @Override
getTag()2039     public int getTag() { return tag; }
2040 
2041     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)2042     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
2043     {
2044         return dest.addDoubleInfo(value);
2045     }
2046 
2047     @Override
write(DataOutputStream out)2048     public void write(DataOutputStream out) throws IOException
2049     {
2050         out.writeByte(tag);
2051         out.writeDouble(value);
2052     }
2053 
2054     @Override
print(PrintWriter out)2055     public void print(PrintWriter out)
2056     {
2057         out.print("Double ");
2058         out.println(value);
2059     }
2060 }
2061 
2062 class Utf8Info extends ConstInfo
2063 {
2064     static final int tag = 1;
2065     String string;
2066 
Utf8Info(String utf8, int index)2067     public Utf8Info(String utf8, int index)
2068     {
2069         super(index);
2070         string = utf8;
2071     }
2072 
Utf8Info(DataInputStream in, int index)2073     public Utf8Info(DataInputStream in, int index)
2074             throws IOException
2075     {
2076         super(index);
2077         string = in.readUTF();
2078     }
2079 
2080     @Override
hashCode()2081     public int hashCode() {
2082         return string.hashCode();
2083     }
2084 
2085     @Override
equals(Object obj)2086     public boolean equals(Object obj) {
2087         return obj instanceof Utf8Info
2088                 && ((Utf8Info)obj).string.equals(string);
2089     }
2090 
2091     @Override
getTag()2092     public int getTag() { return tag; }
2093 
2094     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)2095     public int copy(ConstPool src, ConstPool dest,
2096             Map<String,String> map)
2097     {
2098         return dest.addUtf8Info(string);
2099     }
2100 
2101     @Override
write(DataOutputStream out)2102     public void write(DataOutputStream out)
2103             throws IOException
2104     {
2105         out.writeByte(tag);
2106         out.writeUTF(string);
2107     }
2108 
2109     @Override
print(PrintWriter out)2110     public void print(PrintWriter out) {
2111         out.print("UTF8 \"");
2112         out.print(string);
2113         out.println("\"");
2114     }
2115 }
2116 
2117 class MethodHandleInfo extends ConstInfo {
2118     static final int tag = 15;
2119     int refKind, refIndex;
2120 
MethodHandleInfo(int kind, int referenceIndex, int index)2121     public MethodHandleInfo(int kind, int referenceIndex, int index) {
2122         super(index);
2123         refKind = kind;
2124         refIndex = referenceIndex;
2125     }
2126 
MethodHandleInfo(DataInputStream in, int index)2127     public MethodHandleInfo(DataInputStream in, int index)
2128             throws IOException
2129     {
2130         super(index);
2131         refKind = in.readUnsignedByte();
2132         refIndex = in.readUnsignedShort();
2133     }
2134 
2135     @Override
hashCode()2136     public int hashCode() { return (refKind << 16) ^ refIndex; }
2137 
2138     @Override
equals(Object obj)2139     public boolean equals(Object obj)
2140     {
2141         if (obj instanceof MethodHandleInfo) {
2142             MethodHandleInfo mh = (MethodHandleInfo)obj;
2143             return mh.refKind == refKind && mh.refIndex == refIndex;
2144         }
2145         return false;
2146     }
2147 
2148     @Override
getTag()2149     public int getTag() { return tag; }
2150 
2151     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)2152     public int copy(ConstPool src, ConstPool dest,
2153             Map<String,String> map)
2154     {
2155        return dest.addMethodHandleInfo(refKind,
2156                    src.getItem(refIndex).copy(src, dest, map));
2157     }
2158 
2159     @Override
write(DataOutputStream out)2160     public void write(DataOutputStream out) throws IOException
2161     {
2162         out.writeByte(tag);
2163         out.writeByte(refKind);
2164         out.writeShort(refIndex);
2165     }
2166 
2167     @Override
print(PrintWriter out)2168     public void print(PrintWriter out) {
2169         out.print("MethodHandle #");
2170         out.print(refKind);
2171         out.print(", index #");
2172         out.println(refIndex);
2173     }
2174 }
2175 
2176 class MethodTypeInfo extends ConstInfo
2177 {
2178     static final int tag = 16;
2179     int descriptor;
2180 
MethodTypeInfo(int desc, int index)2181     public MethodTypeInfo(int desc, int index)
2182     {
2183         super(index);
2184         descriptor = desc;
2185     }
2186 
MethodTypeInfo(DataInputStream in, int index)2187     public MethodTypeInfo(DataInputStream in, int index)
2188             throws IOException
2189     {
2190         super(index);
2191         descriptor = in.readUnsignedShort();
2192     }
2193 
2194     @Override
hashCode()2195     public int hashCode() { return descriptor; }
2196 
2197     @Override
equals(Object obj)2198     public boolean equals(Object obj)
2199     {
2200         if (obj instanceof MethodTypeInfo)
2201             return ((MethodTypeInfo)obj).descriptor == descriptor;
2202         return false;
2203     }
2204 
2205     @Override
getTag()2206     public int getTag() { return tag; }
2207 
2208     @Override
renameClass(ConstPool cp, String oldName, String newName, Map<ConstInfo,ConstInfo> cache)2209     public void renameClass(ConstPool cp, String oldName, String newName,
2210             Map<ConstInfo,ConstInfo> cache)
2211     {
2212         String desc = cp.getUtf8Info(descriptor);
2213         String desc2 = Descriptor.rename(desc, oldName, newName);
2214         if (desc != desc2)
2215             if (cache == null)
2216                 descriptor = cp.addUtf8Info(desc2);
2217             else {
2218                 cache.remove(this);
2219                 descriptor = cp.addUtf8Info(desc2);
2220                 cache.put(this, this);
2221             }
2222     }
2223 
2224     @Override
renameClass(ConstPool cp, Map<String,String> map, Map<ConstInfo,ConstInfo> cache)2225     public void renameClass(ConstPool cp, Map<String,String> map,
2226             Map<ConstInfo,ConstInfo> cache)
2227     {
2228         String desc = cp.getUtf8Info(descriptor);
2229         String desc2 = Descriptor.rename(desc, map);
2230         if (desc != desc2)
2231             if (cache == null)
2232                 descriptor = cp.addUtf8Info(desc2);
2233             else {
2234                 cache.remove(this);
2235                 descriptor = cp.addUtf8Info(desc2);
2236                 cache.put(this, this);
2237             }
2238     }
2239 
2240     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)2241     public int copy(ConstPool src, ConstPool dest, Map<String,String> map)
2242     {
2243         String desc = src.getUtf8Info(descriptor);
2244         desc = Descriptor.rename(desc, map);
2245         return dest.addMethodTypeInfo(dest.addUtf8Info(desc));
2246     }
2247 
2248     @Override
write(DataOutputStream out)2249     public void write(DataOutputStream out) throws IOException
2250     {
2251         out.writeByte(tag);
2252         out.writeShort(descriptor);
2253     }
2254 
2255     @Override
print(PrintWriter out)2256     public void print(PrintWriter out) {
2257         out.print("MethodType #");
2258         out.println(descriptor);
2259     }
2260 }
2261 
2262 class InvokeDynamicInfo extends ConstInfo
2263 {
2264     static final int tag = 18;
2265     int bootstrap, nameAndType;
2266 
InvokeDynamicInfo(int bootstrapMethod, int ntIndex, int index)2267     public InvokeDynamicInfo(int bootstrapMethod,
2268             int ntIndex, int index)
2269     {
2270         super(index);
2271         bootstrap = bootstrapMethod;
2272         nameAndType = ntIndex;
2273     }
2274 
InvokeDynamicInfo(DataInputStream in, int index)2275     public InvokeDynamicInfo(DataInputStream in, int index)
2276             throws IOException
2277     {
2278         super(index);
2279         bootstrap = in.readUnsignedShort();
2280         nameAndType = in.readUnsignedShort();
2281     }
2282 
2283     @Override
hashCode()2284     public int hashCode() { return (bootstrap << 16) ^ nameAndType; }
2285 
2286     @Override
equals(Object obj)2287     public boolean equals(Object obj)
2288     {
2289         if (obj instanceof InvokeDynamicInfo) {
2290             InvokeDynamicInfo iv = (InvokeDynamicInfo)obj;
2291             return iv.bootstrap == bootstrap
2292                     && iv.nameAndType == nameAndType;
2293         }
2294         return false;
2295     }
2296 
2297     @Override
getTag()2298     public int getTag() { return tag; }
2299 
2300     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)2301     public int copy(ConstPool src, ConstPool dest,
2302             Map<String,String> map)
2303     {
2304        return dest.addInvokeDynamicInfo(bootstrap,
2305             src.getItem(nameAndType).copy(src, dest, map));
2306     }
2307 
2308     @Override
write(DataOutputStream out)2309     public void write(DataOutputStream out) throws IOException
2310     {
2311         out.writeByte(tag);
2312         out.writeShort(bootstrap);
2313         out.writeShort(nameAndType);
2314     }
2315 
2316     @Override
print(PrintWriter out)2317     public void print(PrintWriter out) {
2318         out.print("InvokeDynamic #");
2319         out.print(bootstrap);
2320         out.print(", name&type #");
2321         out.println(nameAndType);
2322     }
2323 }
2324 
2325 class ModuleInfo extends ConstInfo
2326 {
2327     static final int tag = 19;
2328     int name;
2329 
ModuleInfo(int moduleName, int index)2330     public ModuleInfo(int moduleName, int index)
2331     {
2332         super(index);
2333         name = moduleName;
2334     }
2335 
ModuleInfo(DataInputStream in, int index)2336     public ModuleInfo(DataInputStream in, int index)
2337             throws IOException
2338     {
2339         super(index);
2340         name = in.readUnsignedShort();
2341     }
2342 
2343     @Override
hashCode()2344     public int hashCode() { return name; }
2345 
2346     @Override
equals(Object obj)2347     public boolean equals(Object obj)
2348     {
2349         return obj instanceof ModuleInfo
2350                 && ((ModuleInfo)obj).name == name;
2351     }
2352 
2353     @Override
getTag()2354     public int getTag() { return tag; }
2355 
getModuleName(ConstPool cp)2356     public String getModuleName(ConstPool cp)
2357     {
2358         return cp.getUtf8Info(name);
2359     }
2360 
2361     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)2362     public int copy(ConstPool src, ConstPool dest,
2363             Map<String,String> map)
2364     {
2365         String moduleName = src.getUtf8Info(name);
2366         int newName = dest.addUtf8Info(moduleName);
2367         return dest.addModuleInfo(newName);
2368     }
2369 
2370     @Override
write(DataOutputStream out)2371     public void write(DataOutputStream out) throws IOException
2372     {
2373         out.writeByte(tag);
2374         out.writeShort(name);
2375     }
2376 
2377     @Override
print(PrintWriter out)2378     public void print(PrintWriter out) {
2379         out.print("Module #");
2380         out.println(name);
2381     }
2382 }
2383 
2384 class PackageInfo extends ConstInfo
2385 {
2386     static final int tag = 20;
2387     int name;
2388 
PackageInfo(int moduleName, int index)2389     public PackageInfo(int moduleName, int index)
2390     {
2391         super(index);
2392         name = moduleName;
2393     }
2394 
PackageInfo(DataInputStream in, int index)2395     public PackageInfo(DataInputStream in, int index)
2396             throws IOException
2397     {
2398         super(index);
2399         name = in.readUnsignedShort();
2400     }
2401 
2402     @Override
hashCode()2403     public int hashCode() { return name; }
2404 
2405     @Override
equals(Object obj)2406     public boolean equals(Object obj) {
2407         return obj instanceof PackageInfo
2408                 && ((PackageInfo)obj).name == name;
2409     }
2410 
2411     @Override
getTag()2412     public int getTag() { return tag; }
2413 
getPackageName(ConstPool cp)2414     public String getPackageName(ConstPool cp)
2415     {
2416         return cp.getUtf8Info(name);
2417     }
2418 
2419     @Override
copy(ConstPool src, ConstPool dest, Map<String,String> map)2420     public int copy(ConstPool src, ConstPool dest,
2421             Map<String,String> map)
2422     {
2423         String packageName = src.getUtf8Info(name);
2424         int newName = dest.addUtf8Info(packageName);
2425         return dest.addModuleInfo(newName);
2426     }
2427 
2428     @Override
write(DataOutputStream out)2429     public void write(DataOutputStream out) throws IOException
2430     {
2431         out.writeByte(tag);
2432         out.writeShort(name);
2433     }
2434 
2435     @Override
print(PrintWriter out)2436     public void print(PrintWriter out)
2437     {
2438         out.print("Package #");
2439         out.println(name);
2440     }
2441 }
2442