KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > retrotranslator > runtime > asm > ClassWriter


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30 package net.sf.retrotranslator.runtime.asm;
31
32 /**
33  * A {@link ClassVisitor} that generates classes in bytecode form. More
34  * precisely this visitor generates a byte array conforming to the Java class
35  * file format. It can be used alone, to generate a Java class "from scratch",
36  * or with one or more {@link ClassReader ClassReader} and adapter class visitor
37  * to generate a modified class from one or more existing Java classes.
38  *
39  * @author Eric Bruneton
40  */

41 public class ClassWriter implements ClassVisitor {
42
43     /**
44      * The type of instructions without any argument.
45      */

46     final static int NOARG_INSN = 0;
47
48     /**
49      * The type of instructions with an signed byte argument.
50      */

51     final static int SBYTE_INSN = 1;
52
53     /**
54      * The type of instructions with an signed short argument.
55      */

56     final static int SHORT_INSN = 2;
57
58     /**
59      * The type of instructions with a local variable index argument.
60      */

61     final static int VAR_INSN = 3;
62
63     /**
64      * The type of instructions with an implicit local variable index argument.
65      */

66     final static int IMPLVAR_INSN = 4;
67
68     /**
69      * The type of instructions with a type descriptor argument.
70      */

71     final static int TYPE_INSN = 5;
72
73     /**
74      * The type of field and method invocations instructions.
75      */

76     final static int FIELDORMETH_INSN = 6;
77
78     /**
79      * The type of the INVOKEINTERFACE instruction.
80      */

81     final static int ITFMETH_INSN = 7;
82
83     /**
84      * The type of instructions with a 2 bytes bytecode offset label.
85      */

86     final static int LABEL_INSN = 8;
87
88     /**
89      * The type of instructions with a 4 bytes bytecode offset label.
90      */

91     final static int LABELW_INSN = 9;
92
93     /**
94      * The type of the LDC instruction.
95      */

96     final static int LDC_INSN = 10;
97
98     /**
99      * The type of the LDC_W and LDC2_W instructions.
100      */

101     final static int LDCW_INSN = 11;
102
103     /**
104      * The type of the IINC instruction.
105      */

106     final static int IINC_INSN = 12;
107
108     /**
109      * The type of the TABLESWITCH instruction.
110      */

111     final static int TABL_INSN = 13;
112
113     /**
114      * The type of the LOOKUPSWITCH instruction.
115      */

116     final static int LOOK_INSN = 14;
117
118     /**
119      * The type of the MULTIANEWARRAY instruction.
120      */

121     final static int MANA_INSN = 15;
122
123     /**
124      * The type of the WIDE instruction.
125      */

126     final static int WIDE_INSN = 16;
127
128     /**
129      * The instruction types of all JVM opcodes.
130      */

131     static byte[] TYPE;
132
133     /**
134      * The type of CONSTANT_Class constant pool items.
135      */

136     final static int CLASS = 7;
137
138     /**
139      * The type of CONSTANT_Fieldref constant pool items.
140      */

141     final static int FIELD = 9;
142
143     /**
144      * The type of CONSTANT_Methodref constant pool items.
145      */

146     final static int METH = 10;
147
148     /**
149      * The type of CONSTANT_InterfaceMethodref constant pool items.
150      */

151     final static int IMETH = 11;
152
153     /**
154      * The type of CONSTANT_String constant pool items.
155      */

156     final static int STR = 8;
157
158     /**
159      * The type of CONSTANT_Integer constant pool items.
160      */

161     final static int INT = 3;
162
163     /**
164      * The type of CONSTANT_Float constant pool items.
165      */

166     final static int FLOAT = 4;
167
168     /**
169      * The type of CONSTANT_Long constant pool items.
170      */

171     final static int LONG = 5;
172
173     /**
174      * The type of CONSTANT_Double constant pool items.
175      */

176     final static int DOUBLE = 6;
177
178     /**
179      * The type of CONSTANT_NameAndType constant pool items.
180      */

181     final static int NAME_TYPE = 12;
182
183     /**
184      * The type of CONSTANT_Utf8 constant pool items.
185      */

186     final static int UTF8 = 1;
187
188     /**
189      * The class reader from which this class writer was constructed, if any.
190      */

191     ClassReader cr;
192
193     /**
194      * Minor and major version numbers of the class to be generated.
195      */

196     int version;
197
198     /**
199      * Index of the next item to be added in the constant pool.
200      */

201     int index;
202
203     /**
204      * The constant pool of this class.
205      */

206     ByteVector pool;
207
208     /**
209      * The constant pool's hash table data.
210      */

211     Item[] items;
212
213     /**
214      * The threshold of the constant pool's hash table.
215      */

216     int threshold;
217
218     /**
219      * A reusable key used to look for items in the hash {@link #items items}.
220      */

221     Item key;
222
223     /**
224      * A reusable key used to look for items in the hash {@link #items items}.
225      */

226     Item key2;
227
228     /**
229      * A reusable key used to look for items in the hash {@link #items items}.
230      */

231     Item key3;
232
233     /**
234      * The access flags of this class.
235      */

236     private int access;
237
238     /**
239      * The constant pool item that contains the internal name of this class.
240      */

241     private int name;
242
243     /**
244      * The constant pool item that contains the signature of this class.
245      */

246     private int signature;
247
248     /**
249      * The constant pool item that contains the internal name of the super class
250      * of this class.
251      */

252     private int superName;
253
254     /**
255      * Number of interfaces implemented or extended by this class or interface.
256      */

257     private int interfaceCount;
258
259     /**
260      * The interfaces implemented or extended by this class or interface. More
261      * precisely, this array contains the indexes of the constant pool items
262      * that contain the internal names of these interfaces.
263      */

264     private int[] interfaces;
265
266     /**
267      * The index of the constant pool item that contains the name of the source
268      * file from which this class was compiled.
269      */

270     private int sourceFile;
271
272     /**
273      * The SourceDebug attribute of this class.
274      */

275     private ByteVector sourceDebug;
276
277     /**
278      * The constant pool item that contains the name of the enclosing class of
279      * this class.
280      */

281     private int enclosingMethodOwner;
282
283     /**
284      * The constant pool item that contains the name and descriptor of the
285      * enclosing method of this class.
286      */

287     private int enclosingMethod;
288
289     /**
290      * The runtime visible annotations of this class.
291      */

292     private AnnotationWriter anns;
293
294     /**
295      * The runtime invisible annotations of this class.
296      */

297     private AnnotationWriter ianns;
298
299     /**
300      * The non standard attributes of this class.
301      */

302     private Attribute attrs;
303
304     /**
305      * The number of entries in the InnerClasses attribute.
306      */

307     private int innerClassesCount;
308
309     /**
310      * The InnerClasses attribute.
311      */

312     private ByteVector innerClasses;
313
314     /**
315      * The fields of this class. These fields are stored in a linked list of
316      * {@link FieldWriter} objects, linked to each other by their
317      * {@link FieldWriter#next} field. This field stores the first element of
318      * this list.
319      */

320     FieldWriter firstField;
321
322     /**
323      * The fields of this class. These fields are stored in a linked list of
324      * {@link FieldWriter} objects, linked to each other by their
325      * {@link FieldWriter#next} field. This field stores the last element of
326      * this list.
327      */

328     FieldWriter lastField;
329
330     /**
331      * The methods of this class. These methods are stored in a linked list of
332      * {@link MethodWriter} objects, linked to each other by their
333      * {@link MethodWriter#next} field. This field stores the first element of
334      * this list.
335      */

336     MethodWriter firstMethod;
337
338     /**
339      * The methods of this class. These methods are stored in a linked list of
340      * {@link MethodWriter} objects, linked to each other by their
341      * {@link MethodWriter#next} field. This field stores the last element of
342      * this list.
343      */

344     MethodWriter lastMethod;
345
346     /**
347      * <tt>true</tt> if the maximum stack size and number of local variables
348      * must be automatically computed.
349      */

350     private boolean computeMaxs;
351
352     // ------------------------------------------------------------------------
353
// Static initializer
354
// ------------------------------------------------------------------------
355

356     /**
357      * Computes the instruction types of JVM opcodes.
358      */

359     static {
360         int i;
361         byte[] b = new byte[220];
362         String JavaDoc s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
363                 + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
364                 + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA"
365                 + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII";
366         for (i = 0; i < b.length; ++i) {
367             b[i] = (byte) (s.charAt(i) - 'A');
368         }
369         TYPE = b;
370
371         // code to generate the above string
372
//
373
// // SBYTE_INSN instructions
374
// b[Constants.NEWARRAY] = SBYTE_INSN;
375
// b[Constants.BIPUSH] = SBYTE_INSN;
376
//
377
// // SHORT_INSN instructions
378
// b[Constants.SIPUSH] = SHORT_INSN;
379
//
380
// // (IMPL)VAR_INSN instructions
381
// b[Constants.RET] = VAR_INSN;
382
// for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
383
// b[i] = VAR_INSN;
384
// }
385
// for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
386
// b[i] = VAR_INSN;
387
// }
388
// for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
389
// b[i] = IMPLVAR_INSN;
390
// }
391
// for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
392
// b[i] = IMPLVAR_INSN;
393
// }
394
//
395
// // TYPE_INSN instructions
396
// b[Constants.NEW] = TYPE_INSN;
397
// b[Constants.ANEWARRAY] = TYPE_INSN;
398
// b[Constants.CHECKCAST] = TYPE_INSN;
399
// b[Constants.INSTANCEOF] = TYPE_INSN;
400
//
401
// // (Set)FIELDORMETH_INSN instructions
402
// for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
403
// b[i] = FIELDORMETH_INSN;
404
// }
405
// b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
406
//
407
// // LABEL(W)_INSN instructions
408
// for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
409
// b[i] = LABEL_INSN;
410
// }
411
// b[Constants.IFNULL] = LABEL_INSN;
412
// b[Constants.IFNONNULL] = LABEL_INSN;
413
// b[200] = LABELW_INSN; // GOTO_W
414
// b[201] = LABELW_INSN; // JSR_W
415
// // temporary opcodes used internally by ASM - see Label and
416
// MethodWriter
417
// for (i = 202; i < 220; ++i) {
418
// b[i] = LABEL_INSN;
419
// }
420
//
421
// // LDC(_W) instructions
422
// b[Constants.LDC] = LDC_INSN;
423
// b[19] = LDCW_INSN; // LDC_W
424
// b[20] = LDCW_INSN; // LDC2_W
425
//
426
// // special instructions
427
// b[Constants.IINC] = IINC_INSN;
428
// b[Constants.TABLESWITCH] = TABL_INSN;
429
// b[Constants.LOOKUPSWITCH] = LOOK_INSN;
430
// b[Constants.MULTIANEWARRAY] = MANA_INSN;
431
// b[196] = WIDE_INSN; // WIDE
432
//
433
// for (i = 0; i < b.length; ++i) {
434
// System.err.print((char)('A' + b[i]));
435
// }
436
// System.err.println();
437
}
438
439     // ------------------------------------------------------------------------
440
// Constructor
441
// ------------------------------------------------------------------------
442

443     /**
444      * Constructs a new {@link ClassWriter ClassWriter} object.
445      *
446      * @param computeMaxs <tt>true</tt> if the maximum stack size and the
447      * maximum number of local variables must be automatically computed.
448      * If this flag is <tt>true</tt>, then the arguments of the
449      * {@link MethodVisitor#visitMaxs visitMaxs} method of the
450      * {@link MethodVisitor} returned by the
451      * {@link #visitMethod visitMethod} method will be ignored, and
452      * computed automatically from the signature and the bytecode of each
453      * method.
454      */

455     public ClassWriter(final boolean computeMaxs) {
456         this(computeMaxs, false);
457     }
458
459     /**
460      * Constructs a new {@link ClassWriter} object.
461      *
462      * @param computeMaxs <tt>true</tt> if the maximum stack size and the
463      * maximum number of local variables must be automatically computed.
464      * If this flag is <tt>true</tt>, then the arguments of the
465      * {@link MethodVisitor#visitMaxs visitMaxs} method of the
466      * {@link MethodVisitor} returned by the
467      * {@link #visitMethod visitMethod} method will be ignored, and
468      * computed automatically from the signature and the bytecode of each
469      * method.
470      * @param skipUnknownAttributes <b>Deprecated</b>. The value of this
471      * parameter is ignored.
472      */

473     public ClassWriter(
474         final boolean computeMaxs,
475         final boolean skipUnknownAttributes)
476     {
477         index = 1;
478         pool = new ByteVector();
479         items = new Item[256];
480         threshold = (int) (0.75d * items.length);
481         key = new Item();
482         key2 = new Item();
483         key3 = new Item();
484         this.computeMaxs = computeMaxs;
485     }
486
487     /**
488      * Constructs a new {@link ClassWriter} object and enables optimizations for
489      * "mostly add" bytecode transformations. These optimizations are the
490      * following:
491      *
492      * <ul> <li>The constant pool from the original class is copied as is in
493      * the new class, which saves time. New constant pool entries will be added
494      * at the end if necessary, but unused constant pool entries <i>won't be
495      * removed</i>.</li> <li>Methods that are not transformed are copied as
496      * is in the new class, directly from the original class bytecode (i.e.
497      * without emitting visit events for all the method instructions), which
498      * saves a <i>lot</i> of time. Untransformed methods are detected by the
499      * fact that the {@link ClassReader} receives {@link MethodVisitor} objects
500      * that come from a {@link ClassWriter} (and not from a custom
501      * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li>
502      * </ul>
503      *
504      * @param classReader the {@link ClassReader} used to read the original
505      * class. It will be used to copy the entire constant pool from the
506      * original class and also to copy other fragments of original
507      * bytecode where applicable.
508      * @param computeMaxs <tt>true</tt> if the maximum stack size and the
509      * maximum number of local variables must be automatically computed.
510      * If this flag is <tt>true</tt>, then the arguments of the
511      * {@link MethodVisitor#visitMaxs visitMaxs} method of the
512      * {@link MethodVisitor} returned by the
513      * {@link #visitMethod visitMethod} method will be ignored, and
514      * computed automatically from the signature and the bytecode of each
515      * method.
516      */

517     public ClassWriter(
518         final ClassReader classReader,
519         final boolean computeMaxs)
520     {
521         this(computeMaxs, false);
522         classReader.copyPool(this);
523         this.cr = classReader;
524     }
525
526     // ------------------------------------------------------------------------
527
// Implementation of the ClassVisitor interface
528
// ------------------------------------------------------------------------
529

530     public void visit(
531         final int version,
532         final int access,
533         final String JavaDoc name,
534         final String JavaDoc signature,
535         final String JavaDoc superName,
536         final String JavaDoc[] interfaces)
537     {
538         this.version = version;
539         this.access = access;
540         this.name = newClass(name);
541         if (signature != null) {
542             this.signature = newUTF8(signature);
543         }
544         this.superName = superName == null ? 0 : newClass(superName);
545         if (interfaces != null && interfaces.length > 0) {
546             interfaceCount = interfaces.length;
547             this.interfaces = new int[interfaceCount];
548             for (int i = 0; i < interfaceCount; ++i) {
549                 this.interfaces[i] = newClass(interfaces[i]);
550             }
551         }
552     }
553
554     public void visitSource(final String JavaDoc file, final String JavaDoc debug) {
555         if (file != null) {
556             sourceFile = newUTF8(file);
557         }
558         if (debug != null) {
559             sourceDebug = new ByteVector().putUTF8(debug);
560         }
561     }
562
563     public void visitOuterClass(
564         final String JavaDoc owner,
565         final String JavaDoc name,
566         final String JavaDoc desc)
567     {
568         enclosingMethodOwner = newClass(owner);
569         if (name != null && desc != null) {
570             enclosingMethod = newNameType(name, desc);
571         }
572     }
573
574     public AnnotationVisitor visitAnnotation(String JavaDoc desc, boolean visible) {
575         ByteVector bv = new ByteVector();
576         // write type, and reserve space for values count
577
bv.putShort(newUTF8(desc)).putShort(0);
578         AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
579         if (visible) {
580             aw.next = anns;
581             anns = aw;
582         } else {
583             aw.next = ianns;
584             ianns = aw;
585         }
586         return aw;
587     }
588
589     public void visitAttribute(final Attribute attr) {
590         attr.next = attrs;
591         attrs = attr;
592     }
593
594     public void visitInnerClass(
595         final String JavaDoc name,
596         final String JavaDoc outerName,
597         final String JavaDoc innerName,
598         final int access)
599     {
600         if (innerClasses == null) {
601             innerClasses = new ByteVector();
602         }
603         ++innerClassesCount;
604         innerClasses.putShort(name == null ? 0 : newClass(name));
605         innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
606         innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
607         innerClasses.putShort(access);
608     }
609
610     public FieldVisitor visitField(
611         final int access,
612         final String JavaDoc name,
613         final String JavaDoc desc,
614         final String JavaDoc signature,
615         final Object JavaDoc value)
616     {
617         return new FieldWriter(this, access, name, desc, signature, value);
618     }
619
620     public MethodVisitor visitMethod(
621         final int access,
622         final String JavaDoc name,
623         final String JavaDoc desc,
624         final String JavaDoc signature,
625         final String JavaDoc[] exceptions)
626     {
627         return new MethodWriter(this,
628                 access,
629                 name,
630                 desc,
631                 signature,
632                 exceptions,
633                 computeMaxs);
634     }
635
636     public void visitEnd() {
637     }
638
639     // ------------------------------------------------------------------------
640
// Other public methods
641
// ------------------------------------------------------------------------
642

643     /**
644      * Returns the bytecode of the class that was build with this class writer.
645      *
646      * @return the bytecode of the class that was build with this class writer.
647      */

648     public byte[] toByteArray() {
649         return toByteArray(false);
650     }
651
652     public byte[] toByteArray(boolean dropTigerFlags) {
653         // computes the real size of the bytecode of this class
654
int size = 24 + 2 * interfaceCount;
655         int nbFields = 0;
656         FieldWriter fb = firstField;
657         while (fb != null) {
658             ++nbFields;
659             size += fb.getSize();
660             fb = fb.next;
661         }
662         int nbMethods = 0;
663         MethodWriter mb = firstMethod;
664         while (mb != null) {
665             ++nbMethods;
666             size += mb.getSize();
667             mb = mb.next;
668         }
669         int attributeCount = 0;
670         if (signature != 0) {
671             ++attributeCount;
672             size += 8;
673             newUTF8("Signature");
674         }
675         if (sourceFile != 0) {
676             ++attributeCount;
677             size += 8;
678             newUTF8("SourceFile");
679         }
680         if (sourceDebug != null) {
681             ++attributeCount;
682             size += sourceDebug.length + 4;
683             newUTF8("SourceDebugExtension");
684         }
685         if (enclosingMethodOwner != 0) {
686             ++attributeCount;
687             size += 10;
688             newUTF8("EnclosingMethod");
689         }
690         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
691             ++attributeCount;
692             size += 6;
693             newUTF8("Deprecated");
694         }
695         if ((access & Opcodes.ACC_SYNTHETIC) != 0
696                 && (version & 0xffff) < Opcodes.V1_5)
697         {
698             ++attributeCount;
699             size += 6;
700             newUTF8("Synthetic");
701         }
702         if (version == Opcodes.V1_4) {
703             if ((access & Opcodes.ACC_ANNOTATION) != 0) {
704                 ++attributeCount;
705                 size += 6;
706                 newUTF8("Annotation");
707             }
708             if ((access & Opcodes.ACC_ENUM) != 0) {
709                 ++attributeCount;
710                 size += 6;
711                 newUTF8("Enum");
712             }
713         }
714         if (innerClasses != null) {
715             ++attributeCount;
716             size += 8 + innerClasses.length;
717             newUTF8("InnerClasses");
718         }
719         if (anns != null) {
720             ++attributeCount;
721             size += 8 + anns.getSize();
722             newUTF8("RuntimeVisibleAnnotations");
723         }
724         if (ianns != null) {
725             ++attributeCount;
726             size += 8 + ianns.getSize();
727             newUTF8("RuntimeInvisibleAnnotations");
728         }
729         if (attrs != null) {
730             attributeCount += attrs.getCount();
731             size += attrs.getSize(this, null, 0, -1, -1);
732         }
733         size += pool.length;
734         // allocates a byte vector of this size, in order to avoid unnecessary
735
// arraycopy operations in the ByteVector.enlarge() method
736
ByteVector out = new ByteVector(size);
737         out.putInt(0xCAFEBABE).putInt(version);
738         out.putShort(index).putByteArray(pool.data, 0, pool.length);
739         int modifiers = access;
740         if (dropTigerFlags) {
741             modifiers &= ~(Opcodes.ACC_SYNTHETIC | Opcodes.ACC_ANNOTATION | Opcodes.ACC_ENUM);
742         }
743         out.putShort(modifiers).putShort(name).putShort(superName);
744         out.putShort(interfaceCount);
745         for (int i = 0; i < interfaceCount; ++i) {
746             out.putShort(interfaces[i]);
747         }
748         out.putShort(nbFields);
749         fb = firstField;
750         while (fb != null) {
751             fb.put(out, dropTigerFlags);
752             fb = fb.next;
753         }
754         out.putShort(nbMethods);
755         mb = firstMethod;
756         while (mb != null) {
757             mb.put(out, dropTigerFlags);
758             mb = mb.next;
759         }
760         out.putShort(attributeCount);
761         if (signature != 0) {
762             out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
763         }
764         if (sourceFile != 0) {
765             out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
766         }
767         if (sourceDebug != null) {
768             int len = sourceDebug.length - 2;
769             out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
770             out.putByteArray(sourceDebug.data, 2, len);
771         }
772         if (enclosingMethodOwner != 0) {
773             out.putShort(newUTF8("EnclosingMethod")).putInt(4);
774             out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
775         }
776         if ((access & Opcodes.ACC_DEPRECATED) != 0) {
777             out.putShort(newUTF8("Deprecated")).putInt(0);
778         }
779         if ((access & Opcodes.ACC_SYNTHETIC) != 0
780                 && (version & 0xffff) < Opcodes.V1_5)
781         {
782             out.putShort(newUTF8("Synthetic")).putInt(0);
783         }
784         if (version == Opcodes.V1_4) {
785             if ((access & Opcodes.ACC_ANNOTATION) != 0) {
786                 out.putShort(newUTF8("Annotation")).putInt(0);
787             }
788             if ((access & Opcodes.ACC_ENUM) != 0) {
789                 out.putShort(newUTF8("Enum")).putInt(0);
790             }
791         }
792         if (innerClasses != null) {
793             out.putShort(newUTF8("InnerClasses"));
794             out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
795             out.putByteArray(innerClasses.data, 0, innerClasses.length);
796         }
797         if (anns != null) {
798             out.putShort(newUTF8("RuntimeVisibleAnnotations"));
799             anns.put(out);
800         }
801         if (ianns != null) {
802             out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
803             ianns.put(out);
804         }
805         if (attrs != null) {
806             attrs.put(this, null, 0, -1, -1, out);
807         }
808         return out.data;
809     }
810
811     // ------------------------------------------------------------------------
812
// Utility methods: constant pool management
813
// ------------------------------------------------------------------------
814

815     /**
816      * Adds a number or string constant to the constant pool of the class being
817      * build. Does nothing if the constant pool already contains a similar item.
818      *
819      * @param cst the value of the constant to be added to the constant pool.
820      * This parameter must be an {@link Integer}, a {@link Float}, a
821      * {@link Long}, a {@link Double}, a {@link String} or a
822      * {@link Type}.
823      * @return a new or already existing constant item with the given value.
824      */

825     Item newConstItem(final Object JavaDoc cst) {
826         if (cst instanceof Integer JavaDoc) {
827             int val = ((Integer JavaDoc) cst).intValue();
828             return newInteger(val);
829         } else if (cst instanceof Byte JavaDoc) {
830             int val = ((Byte JavaDoc) cst).intValue();
831             return newInteger(val);
832         } else if (cst instanceof Character JavaDoc) {
833             int val = ((Character JavaDoc) cst).charValue();
834             return newInteger(val);
835         } else if (cst instanceof Short JavaDoc) {
836             int val = ((Short JavaDoc) cst).intValue();
837             return newInteger(val);
838         } else if (cst instanceof Boolean JavaDoc) {
839             int val = ((Boolean JavaDoc) cst).booleanValue() ? 1 : 0;
840             return newInteger(val);
841         } else if (cst instanceof Float JavaDoc) {
842             float val = ((Float JavaDoc) cst).floatValue();
843             return newFloat(val);
844         } else if (cst instanceof Long JavaDoc) {
845             long val = ((Long JavaDoc) cst).longValue();
846             return newLong(val);
847         } else if (cst instanceof Double JavaDoc) {
848             double val = ((Double JavaDoc) cst).doubleValue();
849             return newDouble(val);
850         } else if (cst instanceof String JavaDoc) {
851             return newString((String JavaDoc) cst);
852         } else if (cst instanceof Type) {
853             Type t = (Type) cst;
854             return newClassItem(t.getSort() == Type.OBJECT
855                     ? t.getInternalName()
856                     : t.getDescriptor());
857         } else {
858             throw new IllegalArgumentException JavaDoc("value " + cst);
859         }
860     }
861
862     /**
863      * Adds a number or string constant to the constant pool of the class being
864      * build. Does nothing if the constant pool already contains a similar item.
865      * <i>This method is intended for {@link Attribute} sub classes, and is
866      * normally not needed by class generators or adapters.</i>
867      *
868      * @param cst the value of the constant to be added to the constant pool.
869      * This parameter must be an {@link Integer}, a {@link Float}, a
870      * {@link Long}, a {@link Double} or a {@link String}.
871      * @return the index of a new or already existing constant item with the
872      * given value.
873      */

874     public int newConst(final Object JavaDoc cst) {
875         return newConstItem(cst).index;
876     }
877
878     /**
879      * Adds an UTF8 string to the constant pool of the class being build. Does
880      * nothing if the constant pool already contains a similar item. <i>This
881      * method is intended for {@link Attribute} sub classes, and is normally not
882      * needed by class generators or adapters.</i>
883      *
884      * @param value the String value.
885      * @return the index of a new or already existing UTF8 item.
886      */

887     public int newUTF8(final String JavaDoc value) {
888         key.set(UTF8, value, null, null);
889         Item result = get(key);
890         if (result == null) {
891             pool.putByte(UTF8).putUTF8(value);
892             result = new Item(index++, key);
893             put(result);
894         }
895         return result.index;
896     }
897
898     /**
899      * Adds a class reference to the constant pool of the class being build.
900      * Does nothing if the constant pool already contains a similar item.
901      * <i>This method is intended for {@link Attribute} sub classes, and is
902      * normally not needed by class generators or adapters.</i>
903      *
904      * @param value the internal name of the class.
905      * @return the index of a new or already existing class reference item.
906      */

907     public int newClass(final String JavaDoc value) {
908         return newClassItem(value).index;
909     }
910
911     /**
912      * Adds a class reference to the constant pool of the class being build.
913      * Does nothing if the constant pool already contains a similar item.
914      * <i>This method is intended for {@link Attribute} sub classes, and is
915      * normally not needed by class generators or adapters.</i>
916      *
917      * @param value the internal name of the class.
918      * @return a new or already existing class reference item.
919      */

920     private Item newClassItem(final String JavaDoc value) {
921         key2.set(CLASS, value, null, null);
922         Item result = get(key2);
923         if (result == null) {
924             pool.put12(CLASS, newUTF8(value));
925             result = new Item(index++, key2);
926             put(result);
927         }
928         return result;
929     }
930
931     /**
932      * Adds a field reference to the constant pool of the class being build.
933      * Does nothing if the constant pool already contains a similar item.
934      * <i>This method is intended for {@link Attribute} sub classes, and is
935      * normally not needed by class generators or adapters.</i>
936      *
937      * @param owner the internal name of the field's owner class.
938      * @param name the field's name.
939      * @param desc the field's descriptor.
940      * @return the index of a new or already existing field reference item.
941      */

942     public int newField(final String JavaDoc owner, final String JavaDoc name, final String JavaDoc desc)
943     {
944         key3.set(FIELD, owner, name, desc);
945         Item result = get(key3);
946         if (result == null) {
947             put122(FIELD, newClass(owner), newNameType(name, desc));
948             result = new Item(index++, key3);
949             put(result);
950         }
951         return result.index;
952     }
953
954     /**
955      * Adds a method reference to the constant pool of the class being build.
956      * Does nothing if the constant pool already contains a similar item.
957      *
958      * @param owner the internal name of the method's owner class.
959      * @param name the method's name.
960      * @param desc the method's descriptor.
961      * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
962      * @return a new or already existing method reference item.
963      */

964     Item newMethodItem(
965         final String JavaDoc owner,
966         final String JavaDoc name,
967         final String JavaDoc desc,
968         final boolean itf)
969     {
970         int type = itf ? IMETH : METH;
971         key3.set(type, owner, name, desc);
972         Item result = get(key3);
973         if (result == null) {
974             put122(type, newClass(owner), newNameType(name, desc));
975             result = new Item(index++, key3);
976             put(result);
977         }
978         return result;
979     }
980
981     /**
982      * Adds a method reference to the constant pool of the class being build.
983      * Does nothing if the constant pool already contains a similar item.
984      * <i>This method is intended for {@link Attribute} sub classes, and is
985      * normally not needed by class generators or adapters.</i>
986      *
987      * @param owner the internal name of the method's owner class.
988      * @param name the method's name.
989      * @param desc the method's descriptor.
990      * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
991      * @return the index of a new or already existing method reference item.
992      */

993     public int newMethod(
994         final String JavaDoc owner,
995         final String JavaDoc name,
996         final String JavaDoc desc,
997         final boolean itf)
998     {
999         return newMethodItem(owner, name, desc, itf).index;
1000    }
1001
1002    /**
1003     * Adds an integer to the constant pool of the class being build. Does
1004     * nothing if the constant pool already contains a similar item.
1005     *
1006     * @param value the int value.
1007     * @return a new or already existing int item.
1008     */

1009    Item newInteger(final int value) {
1010        key.set(value);
1011        Item result = get(key);
1012        if (result == null) {
1013            pool.putByte(INT).putInt(value);
1014            result = new Item(index++, key);
1015            put(result);
1016        }
1017        return result;
1018    }
1019
1020    /**
1021     * Adds a float to the constant pool of the class being build. Does nothing
1022     * if the constant pool already contains a similar item.
1023     *
1024     * @param value the float value.
1025     * @return a new or already existing float item.
1026     */

1027    Item newFloat(final float value) {
1028        key.set(value);
1029        Item result = get(key);
1030        if (result == null) {
1031            pool.putByte(FLOAT).putInt(Float.floatToIntBits(value));
1032            result = new Item(index++, key);
1033            put(result);
1034        }
1035        return result;
1036    }
1037
1038    /**
1039     * Adds a long to the constant pool of the class being build. Does nothing
1040     * if the constant pool already contains a similar item.
1041     *
1042     * @param value the long value.
1043     * @return a new or already existing long item.
1044     */

1045    Item newLong(final long value) {
1046        key.set(value);
1047        Item result = get(key);
1048        if (result == null) {
1049            pool.putByte(LONG).putLong(value);
1050            result = new Item(index, key);
1051            put(result);
1052            index += 2;
1053        }
1054        return result;
1055    }
1056
1057    /**
1058     * Adds a double to the constant pool of the class being build. Does nothing
1059     * if the constant pool already contains a similar item.
1060     *
1061     * @param value the double value.
1062     * @return a new or already existing double item.
1063     */

1064    Item newDouble(final double value) {
1065        key.set(value);
1066        Item result = get(key);
1067        if (result == null) {
1068            pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value));
1069            result = new Item(index, key);
1070            put(result);
1071            index += 2;
1072        }
1073        return result;
1074    }
1075
1076    /**
1077     * Adds a string to the constant pool of the class being build. Does nothing
1078     * if the constant pool already contains a similar item.
1079     *
1080     * @param value the String value.
1081     * @return a new or already existing string item.
1082     */

1083    private Item newString(final String JavaDoc value) {
1084        key2.set(STR, value, null, null);
1085        Item result = get(key2);
1086        if (result == null) {
1087            pool.put12(STR, newUTF8(value));
1088            result = new Item(index++, key2);
1089            put(result);
1090        }
1091        return result;
1092    }
1093
1094    /**
1095     * Adds a name and type to the constant pool of the class being build. Does
1096     * nothing if the constant pool already contains a similar item. <i>This
1097     * method is intended for {@link Attribute} sub classes, and is normally not
1098     * needed by class generators or adapters.</i>
1099     *
1100     * @param name a name.
1101     * @param desc a type descriptor.
1102     * @return the index of a new or already existing name and type item.
1103     */

1104    public int newNameType(final String JavaDoc name, final String JavaDoc desc) {
1105        key2.set(NAME_TYPE, name, desc, null);
1106        Item result = get(key2);
1107        if (result == null) {
1108            put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
1109            result = new Item(index++, key2);
1110            put(result);
1111        }
1112        return result.index;
1113    }
1114
1115    /**
1116     * Returns the constant pool's hash table item which is equal to the given
1117     * item.
1118     *
1119     * @param key a constant pool item.
1120     * @return the constant pool's hash table item which is equal to the given
1121     * item, or <tt>null</tt> if there is no such item.
1122     */

1123    private Item get(final Item key) {
1124        Item i = items[key.hashCode % items.length];
1125        while (i != null && !key.isEqualTo(i)) {
1126            i = i.next;
1127        }
1128        return i;
1129    }
1130
1131    /**
1132     * Puts the given item in the constant pool's hash table. The hash table
1133     * <i>must</i> not already contains this item.
1134     *
1135     * @param i the item to be added to the constant pool's hash table.
1136     */

1137    private void put(final Item i) {
1138        if (index > threshold) {
1139            int ll = items.length;
1140            int nl = ll * 2 + 1;
1141            Item[] newItems = new Item[nl];
1142            for (int l = ll - 1; l >= 0; --l) {
1143                Item j = items[l];
1144                while (j != null) {
1145                    int index = j.hashCode % newItems.length;
1146                    Item k = j.next;
1147                    j.next = newItems[index];
1148                    newItems[index] = j;
1149                    j = k;
1150                }
1151            }
1152            items = newItems;
1153            threshold = (int) (nl * 0.75);
1154        }
1155        int index = i.hashCode % items.length;
1156        i.next = items[index];
1157        items[index] = i;
1158    }
1159
1160    /**
1161     * Puts one byte and two shorts into the constant pool.
1162     *
1163     * @param b a byte.
1164     * @param s1 a short.
1165     * @param s2 another short.
1166     */

1167    private void put122(final int b, final int s1, final int s2) {
1168        pool.put12(b, s1).putShort(s2);
1169    }
1170}
1171
Popular Tags