KickJava   Java API By Example, From Geeks To Geeks.

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

807     /**
808      * Adds a number or string constant to the constant pool of the class being
809      * build. Does nothing if the constant pool already contains a similar item.
810      *
811      * @param cst the value of the constant to be added to the constant pool.
812      * This parameter must be an {@link Integer}, a {@link Float}, a
813      * {@link Long}, a {@link Double}, a {@link String} or a
814      * {@link Type}.
815      * @return a new or already existing constant item with the given value.
816      */

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

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

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

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

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

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

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

985     public int newMethod(
986         final String JavaDoc owner,
987         final String JavaDoc name,
988         final String JavaDoc desc,
989         final boolean itf)
990     {
991         return newMethodItem(owner, name, desc, itf).index;
992     }
993
994     /**
995      * Adds an integer to the constant pool of the class being build. Does
996      * nothing if the constant pool already contains a similar item.
997      *
998      * @param value the int value.
999      * @return a new or already existing int item.
1000     */

1001    Item newInteger(final int value) {
1002        key.set(value);
1003        Item result = get(key);
1004        if (result == null) {
1005            pool.putByte(INT).putInt(value);
1006            result = new Item(index++, key);
1007            put(result);
1008        }
1009        return result;
1010    }
1011
1012    /**
1013     * Adds a float to the constant pool of the class being build. Does nothing
1014     * if the constant pool already contains a similar item.
1015     *
1016     * @param value the float value.
1017     * @return a new or already existing float item.
1018     */

1019    Item newFloat(final float value) {
1020        key.set(value);
1021        Item result = get(key);
1022        if (result == null) {
1023            pool.putByte(FLOAT).putInt(Float.floatToIntBits(value));
1024            result = new Item(index++, key);
1025            put(result);
1026        }
1027        return result;
1028    }
1029
1030    /**
1031     * Adds a long to the constant pool of the class being build. Does nothing
1032     * if the constant pool already contains a similar item.
1033     *
1034     * @param value the long value.
1035     * @return a new or already existing long item.
1036     */

1037    Item newLong(final long value) {
1038        key.set(value);
1039        Item result = get(key);
1040        if (result == null) {
1041            pool.putByte(LONG).putLong(value);
1042            result = new Item(index, key);
1043            put(result);
1044            index += 2;
1045        }
1046        return result;
1047    }
1048
1049    /**
1050     * Adds a double to the constant pool of the class being build. Does nothing
1051     * if the constant pool already contains a similar item.
1052     *
1053     * @param value the double value.
1054     * @return a new or already existing double item.
1055     */

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

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

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

1115    private Item get(final Item key) {
1116        Item i = items[key.hashCode % items.length];
1117        while (i != null && !key.isEqualTo(i)) {
1118            i = i.next;
1119        }
1120        return i;
1121    }
1122
1123    /**
1124     * Puts the given item in the constant pool's hash table. The hash table
1125     * <i>must</i> not already contains this item.
1126     *
1127     * @param i the item to be added to the constant pool's hash table.
1128     */

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

1159    private void put122(final int b, final int s1, final int s2) {
1160        pool.put12(b, s1).putShort(s2);
1161    }
1162}
1163
Popular Tags