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 }