View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   package com.sun.org.apache.bcel.internal.generic;
6   
7   /* ====================================================================
8    * The Apache Software License, Version 1.1
9    *
10   * Copyright (c) 2001 The Apache Software Foundation.  All rights
11   * reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions
15   * are met:
16   *
17   * 1. Redistributions of source code must retain the above copyright
18   *    notice, this list of conditions and the following disclaimer.
19   *
20   * 2. Redistributions in binary form must reproduce the above copyright
21   *    notice, this list of conditions and the following disclaimer in
22   *    the documentation and/or other materials provided with the
23   *    distribution.
24   *
25   * 3. The end-user documentation included with the redistribution,
26   *    if any, must include the following acknowledgment:
27   *       "This product includes software developed by the
28   *        Apache Software Foundation (http://www.apache.org/)."
29   *    Alternately, this acknowledgment may appear in the software itself,
30   *    if and wherever such third-party acknowledgments normally appear.
31   *
32   * 4. The names "Apache" and "Apache Software Foundation" and
33   *    "Apache BCEL" must not be used to endorse or promote products
34   *    derived from this software without prior written permission. For
35   *    written permission, please contact apache@apache.org.
36   *
37   * 5. Products derived from this software may not be called "Apache",
38   *    "Apache BCEL", nor may "Apache" appear in their name, without
39   *    prior written permission of the Apache Software Foundation.
40   *
41   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52   * SUCH DAMAGE.
53   * ====================================================================
54   *
55   * This software consists of voluntary contributions made by many
56   * individuals on behalf of the Apache Software Foundation.  For more
57   * information on the Apache Software Foundation, please see
58   * <http://www.apache.org/>.
59   */
60  
61  import com.sun.org.apache.bcel.internal.Constants;
62  import com.sun.org.apache.bcel.internal.classfile.*;
63  import java.util.HashMap;
64  
65  /**
66   * This class is used to build up a constant pool. The user adds
67   * constants via `addXXX' methods, `addString', `addClass',
68   * etc.. These methods return an index into the constant
69   * pool. Finally, `getFinalConstantPool()' returns the constant pool
70   * built up. Intermediate versions of the constant pool can be
71   * obtained with `getConstantPool()'. A constant pool has capacity for
72   * Constants.MAX_SHORT entries. Note that the first (0) is used by the
73   * JVM and that Double and Long constants need two slots.
74   *
75   * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
76   * @see Constant
77   */
78  public class ConstantPoolGen implements java.io.Serializable {
79    protected int        size      = 1024; // Inital size, sufficient in most cases
80    protected Constant[] constants = new Constant[size];
81    protected int        index     = 1; // First entry (0) used by JVM
82  
83    private static final String METHODREF_DELIM  = ":";
84    private static final String IMETHODREF_DELIM = "#";
85    private static final String FIELDREF_DELIM   = "&";
86    private static final String NAT_DELIM        = "%";
87  
88    private static class Index implements java.io.Serializable {
89      int index;
90      Index(int i) { index = i; }
91    }
92  
93    /**
94     * Initialize with given array of constants.
95     *
96     * @param c array of given constants, new ones will be appended
97     */
98    public ConstantPoolGen(Constant[] cs) {
99      if(cs.length > size) {
100       size      = cs.length;
101       constants = new Constant[size];
102     }
103 
104     System.arraycopy(cs, 0, constants, 0, cs.length);
105 
106     if(cs.length > 0)
107       index = cs.length;
108 
109     for(int i=1; i < index; i++) {
110       Constant c = constants[i];
111 
112       if(c instanceof ConstantString) {
113         ConstantString s  = (ConstantString)c;
114         ConstantUtf8   u8 = (ConstantUtf8)constants[s.getStringIndex()];
115 
116         string_table.put(u8.getBytes(), new Index(i));
117       } else if(c instanceof ConstantClass) {
118         ConstantClass s  = (ConstantClass)c;
119         ConstantUtf8  u8 = (ConstantUtf8)constants[s.getNameIndex()];
120 
121         class_table.put(u8.getBytes(), new Index(i));
122       } else if(c instanceof ConstantNameAndType) {
123         ConstantNameAndType n    = (ConstantNameAndType)c;
124         ConstantUtf8        u8   = (ConstantUtf8)constants[n.getNameIndex()];
125         ConstantUtf8        u8_2 = (ConstantUtf8)constants[n.getSignatureIndex()];
126 
127         n_a_t_table.put(u8.getBytes() + NAT_DELIM + u8_2.getBytes(), new Index(i));
128        } else if(c instanceof ConstantUtf8) {
129          ConstantUtf8 u = (ConstantUtf8)c;
130 
131          utf8_table.put(u.getBytes(), new Index(i));
132       } else if(c instanceof ConstantCP) {
133         ConstantCP          m     = (ConstantCP)c;
134         ConstantClass       clazz = (ConstantClass)constants[m.getClassIndex()];
135         ConstantNameAndType n     = (ConstantNameAndType)constants[m.getNameAndTypeIndex()];
136 
137         ConstantUtf8 u8         = (ConstantUtf8)constants[clazz.getNameIndex()];
138         String       class_name = u8.getBytes().replace('/', '.');
139 
140         u8 = (ConstantUtf8)constants[n.getNameIndex()];
141         String method_name = u8.getBytes();
142 
143         u8 = (ConstantUtf8)constants[n.getSignatureIndex()];
144         String signature = u8.getBytes();
145 
146         String delim = METHODREF_DELIM;
147 
148         if(c instanceof ConstantInterfaceMethodref)
149           delim = IMETHODREF_DELIM;
150         else if(c instanceof ConstantFieldref)
151           delim = FIELDREF_DELIM;
152 
153         cp_table.put(class_name + delim + method_name + delim + signature, new Index(i));
154       }
155     }
156   }
157 
158   /**
159    * Initialize with given constant pool.
160    */
161   public ConstantPoolGen(ConstantPool cp) {
162     this(cp.getConstantPool());
163   }
164 
165   /**
166    * Create empty constant pool.
167    */
168   public ConstantPoolGen() {}
169 
170   /** Resize internal array of constants.
171    */
172   protected void adjustSize() {
173     if(index + 3 >= size) {
174       Constant[] cs = constants;
175 
176       size      *= 2;
177       constants  = new Constant[size];
178       System.arraycopy(cs, 0, constants, 0, index);
179     }
180   }
181 
182   private HashMap string_table = new HashMap();
183 
184   /**
185    * Look for ConstantString in ConstantPool containing String `str'.
186    *
187    * @param str String to search for
188    * @return index on success, -1 otherwise
189    */
190   public int lookupString(String str) {
191     Index index = (Index)string_table.get(str);
192     return (index != null)? index.index : -1;
193   }
194 
195   /**
196    * Add a new String constant to the ConstantPool, if it is not already in there.
197    *
198    * @param str String to add
199    * @return index of entry
200    */
201   public int addString(String str) {
202     int ret;
203 
204     if((ret = lookupString(str)) != -1)
205       return ret; // Already in CP
206 
207     int utf8 = addUtf8(str);
208 
209     adjustSize();
210 
211     ConstantString s  = new ConstantString(utf8);
212 
213     ret = index;
214     constants[index++] = s;
215 
216     string_table.put(str, new Index(ret));
217 
218     return ret;
219   }
220 
221   private HashMap class_table = new HashMap();
222 
223   /**
224    * Look for ConstantClass in ConstantPool named `str'.
225    *
226    * @param str String to search for
227    * @return index on success, -1 otherwise
228    */
229   public int lookupClass(String str) {
230     Index index = (Index)class_table.get(str.replace('.', '/'));
231     return (index != null)? index.index : -1;
232   }
233 
234   private int addClass_(String clazz) {
235     int    ret;
236 
237     if((ret = lookupClass(clazz)) != -1)
238       return ret; // Already in CP
239 
240     adjustSize();
241 
242     ConstantClass c = new ConstantClass(addUtf8(clazz));
243 
244     ret = index;
245     constants[index++] = c;
246 
247     class_table.put(clazz, new Index(ret));
248 
249     return ret;
250   }
251 
252   /**
253    * Add a new Class reference to the ConstantPool, if it is not already in there.
254    *
255    * @param str Class to add
256    * @return index of entry
257    */
258   public int addClass(String str) {
259     return addClass_(str.replace('.', '/'));
260   }
261 
262   /**
263    * Add a new Class reference to the ConstantPool for a given type.
264    *
265    * @param str Class to add
266    * @return index of entry
267    */
268   public int addClass(ObjectType type) {
269     return addClass(type.getClassName());
270   }
271 
272   /**
273    * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY
274    * instruction, e.g. to the ConstantPool.
275    *
276    * @param type type of array class
277    * @return index of entry
278    */
279   public int addArrayClass(ArrayType type) {
280     return addClass_(type.getSignature());
281   }
282 
283   /**
284    * Look for ConstantInteger in ConstantPool.
285    *
286    * @param n integer number to look for
287    * @return index on success, -1 otherwise
288    */
289   public int lookupInteger(int n) {
290     for(int i=1; i < index; i++) {
291       if(constants[i] instanceof ConstantInteger) {
292         ConstantInteger c = (ConstantInteger)constants[i];
293 
294         if(c.getBytes() == n)
295           return i;
296       }
297     }
298 
299     return -1;
300   }
301 
302   /**
303    * Add a new Integer constant to the ConstantPool, if it is not already in there.
304    *
305    * @param n integer number to add
306    * @return index of entry
307    */
308   public int addInteger(int n) {
309     int  ret;
310 
311     if((ret = lookupInteger(n)) != -1)
312       return ret; // Already in CP
313 
314     adjustSize();
315 
316     ret = index;
317     constants[index++] = new ConstantInteger(n);
318 
319     return ret;
320   }
321 
322   /**
323    * Look for ConstantFloat in ConstantPool.
324    *
325    * @param n Float number to look for
326    * @return index on success, -1 otherwise
327    */
328   public int lookupFloat(float n) {
329     int bits = Float.floatToIntBits(n);
330 
331     for(int i=1; i < index; i++) {
332       if(constants[i] instanceof ConstantFloat) {
333         ConstantFloat c = (ConstantFloat)constants[i];
334 
335         if(Float.floatToIntBits(c.getBytes()) == bits)
336           return i;
337       }
338     }
339 
340     return -1;
341   }
342 
343   /**
344    * Add a new Float constant to the ConstantPool, if it is not already in there.
345    *
346    * @param n Float number to add
347    * @return index of entry
348    */
349   public int addFloat(float n) {
350     int  ret;
351 
352     if((ret = lookupFloat(n)) != -1)
353       return ret; // Already in CP
354 
355     adjustSize();
356 
357     ret = index;
358     constants[index++] = new ConstantFloat(n);
359 
360     return ret;
361   }
362 
363   private HashMap utf8_table = new HashMap();
364 
365   /**
366    * Look for ConstantUtf8 in ConstantPool.
367    *
368    * @param n Utf8 string to look for
369    * @return index on success, -1 otherwise
370    */
371   public int lookupUtf8(String n) {
372     Index index = (Index)utf8_table.get(n);
373 
374     return (index != null)? index.index : -1;
375   }
376 
377   /**
378    * Add a new Utf8 constant to the ConstantPool, if it is not already in there.
379    *
380    * @param n Utf8 string to add
381    * @return index of entry
382    */
383   public int addUtf8(String n) {
384     int  ret;
385 
386     if((ret = lookupUtf8(n)) != -1)
387       return ret; // Already in CP
388 
389     adjustSize();
390 
391     ret = index;
392     constants[index++] = new ConstantUtf8(n);
393 
394     utf8_table.put(n, new Index(ret));
395 
396     return ret;
397   }
398 
399   /**
400    * Look for ConstantLong in ConstantPool.
401    *
402    * @param n Long number to look for
403    * @return index on success, -1 otherwise
404    */
405   public int lookupLong(long n) {
406     for(int i=1; i < index; i++) {
407       if(constants[i] instanceof ConstantLong) {
408         ConstantLong c = (ConstantLong)constants[i];
409 
410         if(c.getBytes() == n)
411           return i;
412       }
413     }
414 
415     return -1;
416   }
417 
418   /**
419    * Add a new long constant to the ConstantPool, if it is not already in there.
420    *
421    * @param n Long number to add
422    * @return index of entry
423    */
424   public int addLong(long n) {
425     int  ret;
426 
427     if((ret = lookupLong(n)) != -1)
428       return ret; // Already in CP
429 
430     adjustSize();
431 
432     ret = index;
433     constants[index] = new ConstantLong(n);
434     index += 2;   // Wastes one entry according to spec
435 
436     return ret;
437   }
438 
439   /**
440    * Look for ConstantDouble in ConstantPool.
441    *
442    * @param n Double number to look for
443    * @return index on success, -1 otherwise
444    */
445   public int lookupDouble(double n) {
446     long bits = Double.doubleToLongBits(n);
447 
448     for(int i=1; i < index; i++) {
449       if(constants[i] instanceof ConstantDouble) {
450         ConstantDouble c = (ConstantDouble)constants[i];
451 
452         if(Double.doubleToLongBits(c.getBytes()) == bits)
453           return i;
454       }
455     }
456 
457     return -1;
458   }
459 
460   /**
461    * Add a new double constant to the ConstantPool, if it is not already in there.
462    *
463    * @param n Double number to add
464    * @return index of entry
465    */
466   public int addDouble(double n) {
467     int  ret;
468 
469     if((ret = lookupDouble(n)) != -1)
470       return ret; // Already in CP
471 
472     adjustSize();
473 
474     ret = index;
475     constants[index] = new ConstantDouble(n);
476     index += 2;   // Wastes one entry according to spec
477 
478     return ret;
479   }
480 
481   private HashMap n_a_t_table = new HashMap();
482 
483   /**
484    * Look for ConstantNameAndType in ConstantPool.
485    *
486    * @param name of variable/method
487    * @param signature of variable/method
488    * @return index on success, -1 otherwise
489    */
490   public int lookupNameAndType(String name, String signature) {
491     Index index = (Index)n_a_t_table.get(name + NAT_DELIM + signature);
492     return (index != null)? index.index : -1;
493   }
494 
495   /**
496    * Add a new NameAndType constant to the ConstantPool if it is not already
497    * in there.
498    *
499    * @param n NameAndType string to add
500    * @return index of entry
501    */
502   public int addNameAndType(String name, String signature) {
503     int  ret;
504     int  name_index, signature_index;
505 
506     if((ret = lookupNameAndType(name, signature)) != -1)
507       return ret; // Already in CP
508 
509     adjustSize();
510 
511     name_index      = addUtf8(name);
512     signature_index = addUtf8(signature);
513     ret = index;
514     constants[index++] = new ConstantNameAndType(name_index, signature_index);
515 
516     n_a_t_table.put(name + NAT_DELIM + signature, new Index(ret));
517     return ret;
518   }
519 
520   private HashMap cp_table = new HashMap();
521 
522   /**
523    * Look for ConstantMethodref in ConstantPool.
524    *
525    * @param class_name Where to find method
526    * @param method_name Guess what
527    * @param signature return and argument types
528    * @return index on success, -1 otherwise
529    */
530   public int lookupMethodref(String class_name, String method_name, String signature) {
531     Index index = (Index)cp_table.get(class_name + METHODREF_DELIM + method_name +
532                                       METHODREF_DELIM + signature);
533     return (index != null)? index.index : -1;
534   }
535 
536   public int lookupMethodref(MethodGen method) {
537     return lookupMethodref(method.getClassName(), method.getName(),
538                           method.getSignature());
539   }
540 
541   /**
542    * Add a new Methodref constant to the ConstantPool, if it is not already
543    * in there.
544    *
545    * @param n Methodref string to add
546    * @return index of entry
547    */
548   public int addMethodref(String class_name, String method_name, String signature) {
549     int  ret, class_index, name_and_type_index;
550 
551     if((ret = lookupMethodref(class_name, method_name, signature)) != -1)
552       return ret; // Already in CP
553 
554     adjustSize();
555 
556     name_and_type_index = addNameAndType(method_name, signature);
557     class_index         = addClass(class_name);
558     ret = index;
559     constants[index++] = new ConstantMethodref(class_index, name_and_type_index);
560 
561     cp_table.put(class_name + METHODREF_DELIM + method_name +
562                  METHODREF_DELIM + signature, new Index(ret));
563 
564     return ret;
565   }
566 
567   public int addMethodref(MethodGen method) {
568     return addMethodref(method.getClassName(), method.getName(),
569                         method.getSignature());
570   }
571 
572   /**
573    * Look for ConstantInterfaceMethodref in ConstantPool.
574    *
575    * @param class_name Where to find method
576    * @param method_name Guess what
577    * @param signature return and argument types
578    * @return index on success, -1 otherwise
579    */
580   public int lookupInterfaceMethodref(String class_name, String method_name, String signature) {
581     Index index = (Index)cp_table.get(class_name + IMETHODREF_DELIM + method_name +
582                                       IMETHODREF_DELIM + signature);
583     return (index != null)? index.index : -1;
584   }
585 
586   public int lookupInterfaceMethodref(MethodGen method) {
587     return lookupInterfaceMethodref(method.getClassName(), method.getName(),
588                                     method.getSignature());
589   }
590 
591   /**
592    * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already
593    * in there.
594    *
595    * @param n InterfaceMethodref string to add
596    * @return index of entry
597    */
598   public int addInterfaceMethodref(String class_name, String method_name, String signature) {
599     int ret, class_index, name_and_type_index;
600 
601     if((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1)
602       return ret; // Already in CP
603 
604     adjustSize();
605 
606     class_index         = addClass(class_name);
607     name_and_type_index = addNameAndType(method_name, signature);
608     ret = index;
609     constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
610 
611     cp_table.put(class_name + IMETHODREF_DELIM + method_name +
612                  IMETHODREF_DELIM + signature, new Index(ret));
613 
614     return ret;
615   }
616 
617   public int addInterfaceMethodref(MethodGen method) {
618     return addInterfaceMethodref(method.getClassName(), method.getName(),
619                                  method.getSignature());
620   }
621 
622   /**
623    * Look for ConstantFieldref in ConstantPool.
624    *
625    * @param class_name Where to find method
626    * @param field_name Guess what
627    * @param signature return and argument types
628    * @return index on success, -1 otherwise
629    */
630   public int lookupFieldref(String class_name, String field_name, String signature) {
631     Index index = (Index)cp_table.get(class_name + FIELDREF_DELIM + field_name +
632                                       FIELDREF_DELIM + signature);
633     return (index != null)? index.index : -1;
634   }
635 
636   /**
637    * Add a new Fieldref constant to the ConstantPool, if it is not already
638    * in there.
639    *
640    * @param n Fieldref string to add
641    * @return index of entry
642    */
643   public int addFieldref(String class_name, String field_name, String signature) {
644     int  ret;
645     int  class_index, name_and_type_index;
646 
647     if((ret = lookupFieldref(class_name, field_name, signature)) != -1)
648       return ret; // Already in CP
649 
650     adjustSize();
651 
652     class_index         = addClass(class_name);
653     name_and_type_index = addNameAndType(field_name, signature);
654     ret = index;
655     constants[index++] = new ConstantFieldref(class_index, name_and_type_index);
656 
657     cp_table.put(class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature, new Index(ret));
658 
659     return ret;
660   }
661 
662   /**
663    * @param i index in constant pool
664    * @return constant pool entry at index i
665    */
666   public Constant getConstant(int i) { return constants[i]; }
667 
668   /**
669    * Use with care!
670    *
671    * @param i index in constant pool
672    * @param c new constant pool entry at index i
673    */
674   public void setConstant(int i, Constant c) { constants[i] = c; }
675 
676   /**
677    * @return intermediate constant pool
678    */
679   public ConstantPool getConstantPool() {
680     return new ConstantPool(constants);
681   }
682 
683   /**
684    * @return current size of constant pool
685    */
686   public int getSize() {
687     return index;
688   }
689 
690   /**
691    * @return constant pool with proper length
692    */
693   public ConstantPool getFinalConstantPool() {
694     Constant[] cs = new Constant[index];
695 
696     System.arraycopy(constants, 0, cs, 0, index);
697 
698     return new ConstantPool(cs);
699   }
700 
701   /**
702    * @return String representation.
703    */
704   public String toString() {
705     StringBuffer buf = new StringBuffer();
706 
707     for(int i=1; i < index; i++)
708       buf.append(i + ")" + constants[i] + "\n");
709 
710     return buf.toString();
711   }
712 
713   /** Import constant from another ConstantPool and return new index.
714    */
715   public int addConstant(Constant c, ConstantPoolGen cp) {
716     Constant[] constants = cp.getConstantPool().getConstantPool();
717 
718     switch(c.getTag()) {
719     case Constants.CONSTANT_String: {
720       ConstantString s  = (ConstantString)c;
721       ConstantUtf8   u8 = (ConstantUtf8)constants[s.getStringIndex()];
722 
723       return addString(u8.getBytes());
724     }
725 
726     case Constants.CONSTANT_Class: {
727       ConstantClass s  = (ConstantClass)c;
728       ConstantUtf8  u8 = (ConstantUtf8)constants[s.getNameIndex()];
729 
730       return addClass(u8.getBytes());
731     }
732 
733     case Constants.CONSTANT_NameAndType: {
734       ConstantNameAndType n    = (ConstantNameAndType)c;
735       ConstantUtf8        u8   = (ConstantUtf8)constants[n.getNameIndex()];
736       ConstantUtf8        u8_2 = (ConstantUtf8)constants[n.getSignatureIndex()];
737 
738       return addNameAndType(u8.getBytes(), u8_2.getBytes());
739     }
740 
741     case Constants.CONSTANT_Utf8:
742       return addUtf8(((ConstantUtf8)c).getBytes());
743 
744     case Constants.CONSTANT_Double:
745       return addDouble(((ConstantDouble)c).getBytes());
746 
747     case Constants.CONSTANT_Float:
748       return addFloat(((ConstantFloat)c).getBytes());
749 
750     case Constants.CONSTANT_Long:
751       return addLong(((ConstantLong)c).getBytes());
752 
753     case Constants.CONSTANT_Integer:
754       return addInteger(((ConstantInteger)c).getBytes());
755 
756     case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Methodref:
757     case Constants.CONSTANT_Fieldref: {
758       ConstantCP          m     = (ConstantCP)c;
759       ConstantClass       clazz = (ConstantClass)constants[m.getClassIndex()];
760       ConstantNameAndType n     = (ConstantNameAndType)constants[m.getNameAndTypeIndex()];
761       ConstantUtf8 u8           = (ConstantUtf8)constants[clazz.getNameIndex()];
762       String       class_name   = u8.getBytes().replace('/', '.');
763 
764       u8 = (ConstantUtf8)constants[n.getNameIndex()];
765       String name = u8.getBytes();
766 
767       u8 = (ConstantUtf8)constants[n.getSignatureIndex()];
768       String signature = u8.getBytes();
769 
770       switch(c.getTag()) {
771       case Constants.CONSTANT_InterfaceMethodref:
772         return addInterfaceMethodref(class_name, name, signature);
773 
774       case Constants.CONSTANT_Methodref:
775         return addMethodref(class_name, name, signature);
776 
777       case Constants.CONSTANT_Fieldref:
778         return addFieldref(class_name, name, signature);
779 
780       default: // Never reached
781         throw new RuntimeException("Unknown constant type " + c);
782       }
783     }
784 
785     default: // Never reached
786       throw new RuntimeException("Unknown constant type " + c);
787     }
788   }
789 }