View Javadoc

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