• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // ASM: a very small and fast Java bytecode manipulation framework
2 // Copyright (c) 2000-2011 INRIA, France Telecom
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
7 // are met:
8 // 1. Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 //    notice, this list of conditions and the following disclaimer in the
12 //    documentation and/or other materials provided with the distribution.
13 // 3. Neither the name of the copyright holders nor the names of its
14 //    contributors may be used to endorse or promote products derived from
15 //    this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 // THE POSSIBILITY OF SUCH DAMAGE.
28 package org.objectweb.asm;
29 
30 /**
31  * A {@link ClassVisitor} that generates a corresponding ClassFile structure, as defined in the Java
32  * Virtual Machine Specification (JVMS). It can be used alone, to generate a Java class "from
33  * scratch", or with one or more {@link ClassReader} and adapter {@link ClassVisitor} to generate a
34  * modified class from one or more existing Java classes.
35  *
36  * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a>
37  * @author Eric Bruneton
38  */
39 public class ClassWriter extends ClassVisitor {
40 
41   /**
42    * A flag to automatically compute the maximum stack size and the maximum number of local
43    * variables of methods. If this flag is set, then the arguments of the {@link
44    * MethodVisitor#visitMaxs} method of the {@link MethodVisitor} returned by the {@link
45    * #visitMethod} method will be ignored, and computed automatically from the signature and the
46    * bytecode of each method.
47    *
48    * <p><b>Note:</b> for classes whose version is {@link Opcodes#V1_7} of more, this option requires
49    * valid stack map frames. The maximum stack size is then computed from these frames, and from the
50    * bytecode instructions in between. If stack map frames are not present or must be recomputed,
51    * used {@link #COMPUTE_FRAMES} instead.
52    *
53    * @see #ClassWriter(int)
54    */
55   public static final int COMPUTE_MAXS = 1;
56 
57   /**
58    * A flag to automatically compute the stack map frames of methods from scratch. If this flag is
59    * set, then the calls to the {@link MethodVisitor#visitFrame} method are ignored, and the stack
60    * map frames are recomputed from the methods bytecode. The arguments of the {@link
61    * MethodVisitor#visitMaxs} method are also ignored and recomputed from the bytecode. In other
62    * words, {@link #COMPUTE_FRAMES} implies {@link #COMPUTE_MAXS}.
63    *
64    * @see #ClassWriter(int)
65    */
66   public static final int COMPUTE_FRAMES = 2;
67 
68   /**
69    * The flags passed to the constructor. Must be zero or more of {@link #COMPUTE_MAXS} and {@link
70    * #COMPUTE_FRAMES}.
71    */
72   private final int flags;
73 
74   // Note: fields are ordered as in the ClassFile structure, and those related to attributes are
75   // ordered as in Section 4.7 of the JVMS.
76 
77   /**
78    * The minor_version and major_version fields of the JVMS ClassFile structure. minor_version is
79    * stored in the 16 most significant bits, and major_version in the 16 least significant bits.
80    */
81   private int version;
82 
83   /** The symbol table for this class (contains the constant_pool and the BootstrapMethods). */
84   private final SymbolTable symbolTable;
85 
86   /**
87    * The access_flags field of the JVMS ClassFile structure. This field can contain ASM specific
88    * access flags, such as {@link Opcodes#ACC_DEPRECATED} or {@link Opcodes#ACC_RECORD}, which are
89    * removed when generating the ClassFile structure.
90    */
91   private int accessFlags;
92 
93   /** The this_class field of the JVMS ClassFile structure. */
94   private int thisClass;
95 
96   /** The super_class field of the JVMS ClassFile structure. */
97   private int superClass;
98 
99   /** The interface_count field of the JVMS ClassFile structure. */
100   private int interfaceCount;
101 
102   /** The 'interfaces' array of the JVMS ClassFile structure. */
103   private int[] interfaces;
104 
105   /**
106    * The fields of this class, stored in a linked list of {@link FieldWriter} linked via their
107    * {@link FieldWriter#fv} field. This field stores the first element of this list.
108    */
109   private FieldWriter firstField;
110 
111   /**
112    * The fields of this class, stored in a linked list of {@link FieldWriter} linked via their
113    * {@link FieldWriter#fv} field. This field stores the last element of this list.
114    */
115   private FieldWriter lastField;
116 
117   /**
118    * The methods of this class, stored in a linked list of {@link MethodWriter} linked via their
119    * {@link MethodWriter#mv} field. This field stores the first element of this list.
120    */
121   private MethodWriter firstMethod;
122 
123   /**
124    * The methods of this class, stored in a linked list of {@link MethodWriter} linked via their
125    * {@link MethodWriter#mv} field. This field stores the last element of this list.
126    */
127   private MethodWriter lastMethod;
128 
129   /** The number_of_classes field of the InnerClasses attribute, or 0. */
130   private int numberOfInnerClasses;
131 
132   /** The 'classes' array of the InnerClasses attribute, or {@literal null}. */
133   private ByteVector innerClasses;
134 
135   /** The class_index field of the EnclosingMethod attribute, or 0. */
136   private int enclosingClassIndex;
137 
138   /** The method_index field of the EnclosingMethod attribute. */
139   private int enclosingMethodIndex;
140 
141   /** The signature_index field of the Signature attribute, or 0. */
142   private int signatureIndex;
143 
144   /** The source_file_index field of the SourceFile attribute, or 0. */
145   private int sourceFileIndex;
146 
147   /** The debug_extension field of the SourceDebugExtension attribute, or {@literal null}. */
148   private ByteVector debugExtension;
149 
150   /**
151    * The last runtime visible annotation of this class. The previous ones can be accessed with the
152    * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
153    */
154   private AnnotationWriter lastRuntimeVisibleAnnotation;
155 
156   /**
157    * The last runtime invisible annotation of this class. The previous ones can be accessed with the
158    * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
159    */
160   private AnnotationWriter lastRuntimeInvisibleAnnotation;
161 
162   /**
163    * The last runtime visible type annotation of this class. The previous ones can be accessed with
164    * the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
165    */
166   private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
167 
168   /**
169    * The last runtime invisible type annotation of this class. The previous ones can be accessed
170    * with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}.
171    */
172   private AnnotationWriter lastRuntimeInvisibleTypeAnnotation;
173 
174   /** The Module attribute of this class, or {@literal null}. */
175   private ModuleWriter moduleWriter;
176 
177   /** The host_class_index field of the NestHost attribute, or 0. */
178   private int nestHostClassIndex;
179 
180   /** The number_of_classes field of the NestMembers attribute, or 0. */
181   private int numberOfNestMemberClasses;
182 
183   /** The 'classes' array of the NestMembers attribute, or {@literal null}. */
184   private ByteVector nestMemberClasses;
185 
186   /** The number_of_classes field of the PermittedSubclasses attribute, or 0. */
187   private int numberOfPermittedSubclasses;
188 
189   /** The 'classes' array of the PermittedSubclasses attribute, or {@literal null}. */
190   private ByteVector permittedSubclasses;
191 
192   /**
193    * The record components of this class, stored in a linked list of {@link RecordComponentWriter}
194    * linked via their {@link RecordComponentWriter#delegate} field. This field stores the first
195    * element of this list.
196    */
197   private RecordComponentWriter firstRecordComponent;
198 
199   /**
200    * The record components of this class, stored in a linked list of {@link RecordComponentWriter}
201    * linked via their {@link RecordComponentWriter#delegate} field. This field stores the last
202    * element of this list.
203    */
204   private RecordComponentWriter lastRecordComponent;
205 
206   /**
207    * The first non standard attribute of this class. The next ones can be accessed with the {@link
208    * Attribute#nextAttribute} field. May be {@literal null}.
209    *
210    * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
211    * firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
212    * #toByteArray} method writes the attributes in the order defined by this list, i.e. in the
213    * reverse order specified by the user.
214    */
215   private Attribute firstAttribute;
216 
217   /**
218    * Indicates what must be automatically computed in {@link MethodWriter}. Must be one of {@link
219    * MethodWriter#COMPUTE_NOTHING}, {@link MethodWriter#COMPUTE_MAX_STACK_AND_LOCAL}, {@link
220    * MethodWriter#COMPUTE_INSERTED_FRAMES}, or {@link MethodWriter#COMPUTE_ALL_FRAMES}.
221    */
222   private int compute;
223 
224   // -----------------------------------------------------------------------------------------------
225   // Constructor
226   // -----------------------------------------------------------------------------------------------
227 
228   /**
229    * Constructs a new {@link ClassWriter} object.
230    *
231    * @param flags option flags that can be used to modify the default behavior of this class. Must
232    *     be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}.
233    */
ClassWriter(final int flags)234   public ClassWriter(final int flags) {
235     this(null, flags);
236   }
237 
238   /**
239    * Constructs a new {@link ClassWriter} object and enables optimizations for "mostly add" bytecode
240    * transformations. These optimizations are the following:
241    *
242    * <ul>
243    *   <li>The constant pool and bootstrap methods from the original class are copied as is in the
244    *       new class, which saves time. New constant pool entries and new bootstrap methods will be
245    *       added at the end if necessary, but unused constant pool entries or bootstrap methods
246    *       <i>won't be removed</i>.
247    *   <li>Methods that are not transformed are copied as is in the new class, directly from the
248    *       original class bytecode (i.e. without emitting visit events for all the method
249    *       instructions), which saves a <i>lot</i> of time. Untransformed methods are detected by
250    *       the fact that the {@link ClassReader} receives {@link MethodVisitor} objects that come
251    *       from a {@link ClassWriter} (and not from any other {@link ClassVisitor} instance).
252    * </ul>
253    *
254    * @param classReader the {@link ClassReader} used to read the original class. It will be used to
255    *     copy the entire constant pool and bootstrap methods from the original class and also to
256    *     copy other fragments of original bytecode where applicable.
257    * @param flags option flags that can be used to modify the default behavior of this class. Must
258    *     be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. <i>These option flags
259    *     do not affect methods that are copied as is in the new class. This means that neither the
260    *     maximum stack size nor the stack frames will be computed for these methods</i>.
261    */
ClassWriter(final ClassReader classReader, final int flags)262   public ClassWriter(final ClassReader classReader, final int flags) {
263     super(/* latest api = */ Opcodes.ASM9);
264     this.flags = flags;
265     symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader);
266     if ((flags & COMPUTE_FRAMES) != 0) {
267       compute = MethodWriter.COMPUTE_ALL_FRAMES;
268     } else if ((flags & COMPUTE_MAXS) != 0) {
269       compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL;
270     } else {
271       compute = MethodWriter.COMPUTE_NOTHING;
272     }
273   }
274 
275   // -----------------------------------------------------------------------------------------------
276   // Accessors
277   // -----------------------------------------------------------------------------------------------
278 
279   /**
280    * Returns true if all the given flags were passed to the constructor.
281    *
282    * @param flags some option flags. Must be zero or more of {@link #COMPUTE_MAXS} and {@link
283    *     #COMPUTE_FRAMES}.
284    * @return true if all the given flags, or more, were passed to the constructor.
285    */
hasFlags(final int flags)286   public boolean hasFlags(final int flags) {
287     return (this.flags & flags) == flags;
288   }
289 
290   // -----------------------------------------------------------------------------------------------
291   // Implementation of the ClassVisitor abstract class
292   // -----------------------------------------------------------------------------------------------
293 
294   @Override
visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)295   public final void visit(
296       final int version,
297       final int access,
298       final String name,
299       final String signature,
300       final String superName,
301       final String[] interfaces) {
302     this.version = version;
303     this.accessFlags = access;
304     this.thisClass = symbolTable.setMajorVersionAndClassName(version & 0xFFFF, name);
305     if (signature != null) {
306       this.signatureIndex = symbolTable.addConstantUtf8(signature);
307     }
308     this.superClass = superName == null ? 0 : symbolTable.addConstantClass(superName).index;
309     if (interfaces != null && interfaces.length > 0) {
310       interfaceCount = interfaces.length;
311       this.interfaces = new int[interfaceCount];
312       for (int i = 0; i < interfaceCount; ++i) {
313         this.interfaces[i] = symbolTable.addConstantClass(interfaces[i]).index;
314       }
315     }
316     if (compute == MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL && (version & 0xFFFF) >= Opcodes.V1_7) {
317       compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES;
318     }
319   }
320 
321   @Override
visitSource(final String file, final String debug)322   public final void visitSource(final String file, final String debug) {
323     if (file != null) {
324       sourceFileIndex = symbolTable.addConstantUtf8(file);
325     }
326     if (debug != null) {
327       debugExtension = new ByteVector().encodeUtf8(debug, 0, Integer.MAX_VALUE);
328     }
329   }
330 
331   @Override
visitModule( final String name, final int access, final String version)332   public final ModuleVisitor visitModule(
333       final String name, final int access, final String version) {
334     return moduleWriter =
335         new ModuleWriter(
336             symbolTable,
337             symbolTable.addConstantModule(name).index,
338             access,
339             version == null ? 0 : symbolTable.addConstantUtf8(version));
340   }
341 
342   @Override
visitNestHost(final String nestHost)343   public final void visitNestHost(final String nestHost) {
344     nestHostClassIndex = symbolTable.addConstantClass(nestHost).index;
345   }
346 
347   @Override
visitOuterClass( final String owner, final String name, final String descriptor)348   public final void visitOuterClass(
349       final String owner, final String name, final String descriptor) {
350     enclosingClassIndex = symbolTable.addConstantClass(owner).index;
351     if (name != null && descriptor != null) {
352       enclosingMethodIndex = symbolTable.addConstantNameAndType(name, descriptor);
353     }
354   }
355 
356   @Override
visitAnnotation(final String descriptor, final boolean visible)357   public final AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
358     if (visible) {
359       return lastRuntimeVisibleAnnotation =
360           AnnotationWriter.create(symbolTable, descriptor, lastRuntimeVisibleAnnotation);
361     } else {
362       return lastRuntimeInvisibleAnnotation =
363           AnnotationWriter.create(symbolTable, descriptor, lastRuntimeInvisibleAnnotation);
364     }
365   }
366 
367   @Override
visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)368   public final AnnotationVisitor visitTypeAnnotation(
369       final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
370     if (visible) {
371       return lastRuntimeVisibleTypeAnnotation =
372           AnnotationWriter.create(
373               symbolTable, typeRef, typePath, descriptor, lastRuntimeVisibleTypeAnnotation);
374     } else {
375       return lastRuntimeInvisibleTypeAnnotation =
376           AnnotationWriter.create(
377               symbolTable, typeRef, typePath, descriptor, lastRuntimeInvisibleTypeAnnotation);
378     }
379   }
380 
381   @Override
visitAttribute(final Attribute attribute)382   public final void visitAttribute(final Attribute attribute) {
383     // Store the attributes in the <i>reverse</i> order of their visit by this method.
384     attribute.nextAttribute = firstAttribute;
385     firstAttribute = attribute;
386   }
387 
388   @Override
visitNestMember(final String nestMember)389   public final void visitNestMember(final String nestMember) {
390     if (nestMemberClasses == null) {
391       nestMemberClasses = new ByteVector();
392     }
393     ++numberOfNestMemberClasses;
394     nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index);
395   }
396 
397   @Override
visitPermittedSubclass(final String permittedSubclass)398   public final void visitPermittedSubclass(final String permittedSubclass) {
399     if (permittedSubclasses == null) {
400       permittedSubclasses = new ByteVector();
401     }
402     ++numberOfPermittedSubclasses;
403     permittedSubclasses.putShort(symbolTable.addConstantClass(permittedSubclass).index);
404   }
405 
406   @Override
visitInnerClass( final String name, final String outerName, final String innerName, final int access)407   public final void visitInnerClass(
408       final String name, final String outerName, final String innerName, final int access) {
409     if (innerClasses == null) {
410       innerClasses = new ByteVector();
411     }
412     // Section 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the constant_pool table
413     // which represents a class or interface C that is not a package member must have exactly one
414     // corresponding entry in the classes array". To avoid duplicates we keep track in the info
415     // field of the Symbol of each CONSTANT_Class_info entry C whether an inner class entry has
416     // already been added for C. If so, we store the index of this inner class entry (plus one) in
417     // the info field. This trick allows duplicate detection in O(1) time.
418     Symbol nameSymbol = symbolTable.addConstantClass(name);
419     if (nameSymbol.info == 0) {
420       ++numberOfInnerClasses;
421       innerClasses.putShort(nameSymbol.index);
422       innerClasses.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index);
423       innerClasses.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName));
424       innerClasses.putShort(access);
425       nameSymbol.info = numberOfInnerClasses;
426     }
427     // Else, compare the inner classes entry nameSymbol.info - 1 with the arguments of this method
428     // and throw an exception if there is a difference?
429   }
430 
431   @Override
visitRecordComponent( final String name, final String descriptor, final String signature)432   public final RecordComponentVisitor visitRecordComponent(
433       final String name, final String descriptor, final String signature) {
434     RecordComponentWriter recordComponentWriter =
435         new RecordComponentWriter(symbolTable, name, descriptor, signature);
436     if (firstRecordComponent == null) {
437       firstRecordComponent = recordComponentWriter;
438     } else {
439       lastRecordComponent.delegate = recordComponentWriter;
440     }
441     return lastRecordComponent = recordComponentWriter;
442   }
443 
444   @Override
visitField( final int access, final String name, final String descriptor, final String signature, final Object value)445   public final FieldVisitor visitField(
446       final int access,
447       final String name,
448       final String descriptor,
449       final String signature,
450       final Object value) {
451     FieldWriter fieldWriter =
452         new FieldWriter(symbolTable, access, name, descriptor, signature, value);
453     if (firstField == null) {
454       firstField = fieldWriter;
455     } else {
456       lastField.fv = fieldWriter;
457     }
458     return lastField = fieldWriter;
459   }
460 
461   @Override
visitMethod( final int access, final String name, final String descriptor, final String signature, final String[] exceptions)462   public final MethodVisitor visitMethod(
463       final int access,
464       final String name,
465       final String descriptor,
466       final String signature,
467       final String[] exceptions) {
468     MethodWriter methodWriter =
469         new MethodWriter(symbolTable, access, name, descriptor, signature, exceptions, compute);
470     if (firstMethod == null) {
471       firstMethod = methodWriter;
472     } else {
473       lastMethod.mv = methodWriter;
474     }
475     return lastMethod = methodWriter;
476   }
477 
478   @Override
visitEnd()479   public final void visitEnd() {
480     // Nothing to do.
481   }
482 
483   // -----------------------------------------------------------------------------------------------
484   // Other public methods
485   // -----------------------------------------------------------------------------------------------
486 
487   /**
488    * Returns the content of the class file that was built by this ClassWriter.
489    *
490    * @return the binary content of the JVMS ClassFile structure that was built by this ClassWriter.
491    * @throws ClassTooLargeException if the constant pool of the class is too large.
492    * @throws MethodTooLargeException if the Code attribute of a method is too large.
493    */
toByteArray()494   public byte[] toByteArray() {
495     // First step: compute the size in bytes of the ClassFile structure.
496     // The magic field uses 4 bytes, 10 mandatory fields (minor_version, major_version,
497     // constant_pool_count, access_flags, this_class, super_class, interfaces_count, fields_count,
498     // methods_count and attributes_count) use 2 bytes each, and each interface uses 2 bytes too.
499     int size = 24 + 2 * interfaceCount;
500     int fieldsCount = 0;
501     FieldWriter fieldWriter = firstField;
502     while (fieldWriter != null) {
503       ++fieldsCount;
504       size += fieldWriter.computeFieldInfoSize();
505       fieldWriter = (FieldWriter) fieldWriter.fv;
506     }
507     int methodsCount = 0;
508     MethodWriter methodWriter = firstMethod;
509     while (methodWriter != null) {
510       ++methodsCount;
511       size += methodWriter.computeMethodInfoSize();
512       methodWriter = (MethodWriter) methodWriter.mv;
513     }
514 
515     // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
516     int attributesCount = 0;
517     if (innerClasses != null) {
518       ++attributesCount;
519       size += 8 + innerClasses.length;
520       symbolTable.addConstantUtf8(Constants.INNER_CLASSES);
521     }
522     if (enclosingClassIndex != 0) {
523       ++attributesCount;
524       size += 10;
525       symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD);
526     }
527     if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) {
528       ++attributesCount;
529       size += 6;
530       symbolTable.addConstantUtf8(Constants.SYNTHETIC);
531     }
532     if (signatureIndex != 0) {
533       ++attributesCount;
534       size += 8;
535       symbolTable.addConstantUtf8(Constants.SIGNATURE);
536     }
537     if (sourceFileIndex != 0) {
538       ++attributesCount;
539       size += 8;
540       symbolTable.addConstantUtf8(Constants.SOURCE_FILE);
541     }
542     if (debugExtension != null) {
543       ++attributesCount;
544       size += 6 + debugExtension.length;
545       symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION);
546     }
547     if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
548       ++attributesCount;
549       size += 6;
550       symbolTable.addConstantUtf8(Constants.DEPRECATED);
551     }
552     if (lastRuntimeVisibleAnnotation != null) {
553       ++attributesCount;
554       size +=
555           lastRuntimeVisibleAnnotation.computeAnnotationsSize(
556               Constants.RUNTIME_VISIBLE_ANNOTATIONS);
557     }
558     if (lastRuntimeInvisibleAnnotation != null) {
559       ++attributesCount;
560       size +=
561           lastRuntimeInvisibleAnnotation.computeAnnotationsSize(
562               Constants.RUNTIME_INVISIBLE_ANNOTATIONS);
563     }
564     if (lastRuntimeVisibleTypeAnnotation != null) {
565       ++attributesCount;
566       size +=
567           lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize(
568               Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
569     }
570     if (lastRuntimeInvisibleTypeAnnotation != null) {
571       ++attributesCount;
572       size +=
573           lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize(
574               Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
575     }
576     if (symbolTable.computeBootstrapMethodsSize() > 0) {
577       ++attributesCount;
578       size += symbolTable.computeBootstrapMethodsSize();
579     }
580     if (moduleWriter != null) {
581       attributesCount += moduleWriter.getAttributeCount();
582       size += moduleWriter.computeAttributesSize();
583     }
584     if (nestHostClassIndex != 0) {
585       ++attributesCount;
586       size += 8;
587       symbolTable.addConstantUtf8(Constants.NEST_HOST);
588     }
589     if (nestMemberClasses != null) {
590       ++attributesCount;
591       size += 8 + nestMemberClasses.length;
592       symbolTable.addConstantUtf8(Constants.NEST_MEMBERS);
593     }
594     if (permittedSubclasses != null) {
595       ++attributesCount;
596       size += 8 + permittedSubclasses.length;
597       symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES);
598     }
599     int recordComponentCount = 0;
600     int recordSize = 0;
601     if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) {
602       RecordComponentWriter recordComponentWriter = firstRecordComponent;
603       while (recordComponentWriter != null) {
604         ++recordComponentCount;
605         recordSize += recordComponentWriter.computeRecordComponentInfoSize();
606         recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
607       }
608       ++attributesCount;
609       size += 8 + recordSize;
610       symbolTable.addConstantUtf8(Constants.RECORD);
611     }
612     if (firstAttribute != null) {
613       attributesCount += firstAttribute.getAttributeCount();
614       size += firstAttribute.computeAttributesSize(symbolTable);
615     }
616     // IMPORTANT: this must be the last part of the ClassFile size computation, because the previous
617     // statements can add attribute names to the constant pool, thereby changing its size!
618     size += symbolTable.getConstantPoolLength();
619     int constantPoolCount = symbolTable.getConstantPoolCount();
620     if (constantPoolCount > 0xFFFF) {
621       throw new ClassTooLargeException(symbolTable.getClassName(), constantPoolCount);
622     }
623 
624     // Second step: allocate a ByteVector of the correct size (in order to avoid any array copy in
625     // dynamic resizes) and fill it with the ClassFile content.
626     ByteVector result = new ByteVector(size);
627     result.putInt(0xCAFEBABE).putInt(version);
628     symbolTable.putConstantPool(result);
629     int mask = (version & 0xFFFF) < Opcodes.V1_5 ? Opcodes.ACC_SYNTHETIC : 0;
630     result.putShort(accessFlags & ~mask).putShort(thisClass).putShort(superClass);
631     result.putShort(interfaceCount);
632     for (int i = 0; i < interfaceCount; ++i) {
633       result.putShort(interfaces[i]);
634     }
635     result.putShort(fieldsCount);
636     fieldWriter = firstField;
637     while (fieldWriter != null) {
638       fieldWriter.putFieldInfo(result);
639       fieldWriter = (FieldWriter) fieldWriter.fv;
640     }
641     result.putShort(methodsCount);
642     boolean hasFrames = false;
643     boolean hasAsmInstructions = false;
644     methodWriter = firstMethod;
645     while (methodWriter != null) {
646       hasFrames |= methodWriter.hasFrames();
647       hasAsmInstructions |= methodWriter.hasAsmInstructions();
648       methodWriter.putMethodInfo(result);
649       methodWriter = (MethodWriter) methodWriter.mv;
650     }
651     // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
652     result.putShort(attributesCount);
653     if (innerClasses != null) {
654       result
655           .putShort(symbolTable.addConstantUtf8(Constants.INNER_CLASSES))
656           .putInt(innerClasses.length + 2)
657           .putShort(numberOfInnerClasses)
658           .putByteArray(innerClasses.data, 0, innerClasses.length);
659     }
660     if (enclosingClassIndex != 0) {
661       result
662           .putShort(symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD))
663           .putInt(4)
664           .putShort(enclosingClassIndex)
665           .putShort(enclosingMethodIndex);
666     }
667     if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) {
668       result.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0);
669     }
670     if (signatureIndex != 0) {
671       result
672           .putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE))
673           .putInt(2)
674           .putShort(signatureIndex);
675     }
676     if (sourceFileIndex != 0) {
677       result
678           .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_FILE))
679           .putInt(2)
680           .putShort(sourceFileIndex);
681     }
682     if (debugExtension != null) {
683       int length = debugExtension.length;
684       result
685           .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION))
686           .putInt(length)
687           .putByteArray(debugExtension.data, 0, length);
688     }
689     if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
690       result.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0);
691     }
692     AnnotationWriter.putAnnotations(
693         symbolTable,
694         lastRuntimeVisibleAnnotation,
695         lastRuntimeInvisibleAnnotation,
696         lastRuntimeVisibleTypeAnnotation,
697         lastRuntimeInvisibleTypeAnnotation,
698         result);
699     symbolTable.putBootstrapMethods(result);
700     if (moduleWriter != null) {
701       moduleWriter.putAttributes(result);
702     }
703     if (nestHostClassIndex != 0) {
704       result
705           .putShort(symbolTable.addConstantUtf8(Constants.NEST_HOST))
706           .putInt(2)
707           .putShort(nestHostClassIndex);
708     }
709     if (nestMemberClasses != null) {
710       result
711           .putShort(symbolTable.addConstantUtf8(Constants.NEST_MEMBERS))
712           .putInt(nestMemberClasses.length + 2)
713           .putShort(numberOfNestMemberClasses)
714           .putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length);
715     }
716     if (permittedSubclasses != null) {
717       result
718           .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES))
719           .putInt(permittedSubclasses.length + 2)
720           .putShort(numberOfPermittedSubclasses)
721           .putByteArray(permittedSubclasses.data, 0, permittedSubclasses.length);
722     }
723     if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) {
724       result
725           .putShort(symbolTable.addConstantUtf8(Constants.RECORD))
726           .putInt(recordSize + 2)
727           .putShort(recordComponentCount);
728       RecordComponentWriter recordComponentWriter = firstRecordComponent;
729       while (recordComponentWriter != null) {
730         recordComponentWriter.putRecordComponentInfo(result);
731         recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
732       }
733     }
734     if (firstAttribute != null) {
735       firstAttribute.putAttributes(symbolTable, result);
736     }
737 
738     // Third step: replace the ASM specific instructions, if any.
739     if (hasAsmInstructions) {
740       return replaceAsmInstructions(result.data, hasFrames);
741     } else {
742       return result.data;
743     }
744   }
745 
746   /**
747    * Returns the equivalent of the given class file, with the ASM specific instructions replaced
748    * with standard ones. This is done with a ClassReader -&gt; ClassWriter round trip.
749    *
750    * @param classFile a class file containing ASM specific instructions, generated by this
751    *     ClassWriter.
752    * @param hasFrames whether there is at least one stack map frames in 'classFile'.
753    * @return an equivalent of 'classFile', with the ASM specific instructions replaced with standard
754    *     ones.
755    */
756   private byte[] replaceAsmInstructions(final byte[] classFile, final boolean hasFrames) {
757     final Attribute[] attributes = getAttributePrototypes();
758     firstField = null;
759     lastField = null;
760     firstMethod = null;
761     lastMethod = null;
762     lastRuntimeVisibleAnnotation = null;
763     lastRuntimeInvisibleAnnotation = null;
764     lastRuntimeVisibleTypeAnnotation = null;
765     lastRuntimeInvisibleTypeAnnotation = null;
766     moduleWriter = null;
767     nestHostClassIndex = 0;
768     numberOfNestMemberClasses = 0;
769     nestMemberClasses = null;
770     numberOfPermittedSubclasses = 0;
771     permittedSubclasses = null;
772     firstRecordComponent = null;
773     lastRecordComponent = null;
774     firstAttribute = null;
775     compute = hasFrames ? MethodWriter.COMPUTE_INSERTED_FRAMES : MethodWriter.COMPUTE_NOTHING;
776     new ClassReader(classFile, 0, /* checkClassVersion = */ false)
777         .accept(
778             this,
779             attributes,
780             (hasFrames ? ClassReader.EXPAND_FRAMES : 0) | ClassReader.EXPAND_ASM_INSNS);
781     return toByteArray();
782   }
783 
784   /**
785    * Returns the prototypes of the attributes used by this class, its fields and its methods.
786    *
787    * @return the prototypes of the attributes used by this class, its fields and its methods.
788    */
789   private Attribute[] getAttributePrototypes() {
790     Attribute.Set attributePrototypes = new Attribute.Set();
791     attributePrototypes.addAttributes(firstAttribute);
792     FieldWriter fieldWriter = firstField;
793     while (fieldWriter != null) {
794       fieldWriter.collectAttributePrototypes(attributePrototypes);
795       fieldWriter = (FieldWriter) fieldWriter.fv;
796     }
797     MethodWriter methodWriter = firstMethod;
798     while (methodWriter != null) {
799       methodWriter.collectAttributePrototypes(attributePrototypes);
800       methodWriter = (MethodWriter) methodWriter.mv;
801     }
802     RecordComponentWriter recordComponentWriter = firstRecordComponent;
803     while (recordComponentWriter != null) {
804       recordComponentWriter.collectAttributePrototypes(attributePrototypes);
805       recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
806     }
807     return attributePrototypes.toArray();
808   }
809 
810   // -----------------------------------------------------------------------------------------------
811   // Utility methods: constant pool management for Attribute sub classes
812   // -----------------------------------------------------------------------------------------------
813 
814   /**
815    * Adds a number or string constant to the constant pool of the class being build. Does nothing if
816    * the constant pool already contains a similar item. <i>This method is intended for {@link
817    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
818    *
819    * @param value the value of the constant to be added to the constant pool. This parameter must be
820    *     an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
821    * @return the index of a new or already existing constant item with the given value.
822    */
823   public int newConst(final Object value) {
824     return symbolTable.addConstant(value).index;
825   }
826 
827   /**
828    * Adds an UTF8 string to the constant pool of the class being build. Does nothing if the constant
829    * pool already contains a similar item. <i>This method is intended for {@link Attribute} sub
830    * classes, and is normally not needed by class generators or adapters.</i>
831    *
832    * @param value the String value.
833    * @return the index of a new or already existing UTF8 item.
834    */
835   // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
836   public int newUTF8(final String value) {
837     return symbolTable.addConstantUtf8(value);
838   }
839 
840   /**
841    * Adds a class reference to the constant pool of the class being build. Does nothing if the
842    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
843    * sub classes, and is normally not needed by class generators or adapters.</i>
844    *
845    * @param value the internal name of the class (see {@link Type#getInternalName()}).
846    * @return the index of a new or already existing class reference item.
847    */
848   public int newClass(final String value) {
849     return symbolTable.addConstantClass(value).index;
850   }
851 
852   /**
853    * Adds a method type reference to the constant pool of the class being build. Does nothing if the
854    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
855    * sub classes, and is normally not needed by class generators or adapters.</i>
856    *
857    * @param methodDescriptor method descriptor of the method type.
858    * @return the index of a new or already existing method type reference item.
859    */
860   public int newMethodType(final String methodDescriptor) {
861     return symbolTable.addConstantMethodType(methodDescriptor).index;
862   }
863 
864   /**
865    * Adds a module reference to the constant pool of the class being build. Does nothing if the
866    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
867    * sub classes, and is normally not needed by class generators or adapters.</i>
868    *
869    * @param moduleName name of the module.
870    * @return the index of a new or already existing module reference item.
871    */
872   public int newModule(final String moduleName) {
873     return symbolTable.addConstantModule(moduleName).index;
874   }
875 
876   /**
877    * Adds a package reference to the constant pool of the class being build. Does nothing if the
878    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
879    * sub classes, and is normally not needed by class generators or adapters.</i>
880    *
881    * @param packageName name of the package in its internal form.
882    * @return the index of a new or already existing module reference item.
883    */
884   public int newPackage(final String packageName) {
885     return symbolTable.addConstantPackage(packageName).index;
886   }
887 
888   /**
889    * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool
890    * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes,
891    * and is normally not needed by class generators or adapters.</i>
892    *
893    * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link
894    *     Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
895    *     Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
896    *     {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
897    * @param owner the internal name of the field or method owner class (see {@link
898    *     Type#getInternalName()}).
899    * @param name the name of the field or method.
900    * @param descriptor the descriptor of the field or method.
901    * @return the index of a new or already existing method type reference item.
902    * @deprecated this method is superseded by {@link #newHandle(int, String, String, String,
903    *     boolean)}.
904    */
905   @Deprecated
906   public int newHandle(
907       final int tag, final String owner, final String name, final String descriptor) {
908     return newHandle(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE);
909   }
910 
911   /**
912    * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool
913    * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes,
914    * and is normally not needed by class generators or adapters.</i>
915    *
916    * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link
917    *     Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
918    *     Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
919    *     {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
920    * @param owner the internal name of the field or method owner class (see {@link
921    *     Type#getInternalName()}).
922    * @param name the name of the field or method.
923    * @param descriptor the descriptor of the field or method.
924    * @param isInterface true if the owner is an interface.
925    * @return the index of a new or already existing method type reference item.
926    */
927   public int newHandle(
928       final int tag,
929       final String owner,
930       final String name,
931       final String descriptor,
932       final boolean isInterface) {
933     return symbolTable.addConstantMethodHandle(tag, owner, name, descriptor, isInterface).index;
934   }
935 
936   /**
937    * Adds a dynamic constant reference to the constant pool of the class being build. Does nothing
938    * if the constant pool already contains a similar item. <i>This method is intended for {@link
939    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
940    *
941    * @param name name of the invoked method.
942    * @param descriptor field descriptor of the constant type.
943    * @param bootstrapMethodHandle the bootstrap method.
944    * @param bootstrapMethodArguments the bootstrap method constant arguments.
945    * @return the index of a new or already existing dynamic constant reference item.
946    */
947   public int newConstantDynamic(
948       final String name,
949       final String descriptor,
950       final Handle bootstrapMethodHandle,
951       final Object... bootstrapMethodArguments) {
952     return symbolTable.addConstantDynamic(
953             name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments)
954         .index;
955   }
956 
957   /**
958    * Adds an invokedynamic reference to the constant pool of the class being build. Does nothing if
959    * the constant pool already contains a similar item. <i>This method is intended for {@link
960    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
961    *
962    * @param name name of the invoked method.
963    * @param descriptor descriptor of the invoke method.
964    * @param bootstrapMethodHandle the bootstrap method.
965    * @param bootstrapMethodArguments the bootstrap method constant arguments.
966    * @return the index of a new or already existing invokedynamic reference item.
967    */
968   public int newInvokeDynamic(
969       final String name,
970       final String descriptor,
971       final Handle bootstrapMethodHandle,
972       final Object... bootstrapMethodArguments) {
973     return symbolTable.addConstantInvokeDynamic(
974             name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments)
975         .index;
976   }
977 
978   /**
979    * Adds a field reference to the constant pool of the class being build. Does nothing if the
980    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
981    * sub classes, and is normally not needed by class generators or adapters.</i>
982    *
983    * @param owner the internal name of the field's owner class (see {@link Type#getInternalName()}).
984    * @param name the field's name.
985    * @param descriptor the field's descriptor.
986    * @return the index of a new or already existing field reference item.
987    */
988   public int newField(final String owner, final String name, final String descriptor) {
989     return symbolTable.addConstantFieldref(owner, name, descriptor).index;
990   }
991 
992   /**
993    * Adds a method reference to the constant pool of the class being build. Does nothing if the
994    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
995    * sub classes, and is normally not needed by class generators or adapters.</i>
996    *
997    * @param owner the internal name of the method's owner class (see {@link
998    *     Type#getInternalName()}).
999    * @param name the method's name.
1000    * @param descriptor the method's descriptor.
1001    * @param isInterface {@literal true} if {@code owner} is an interface.
1002    * @return the index of a new or already existing method reference item.
1003    */
1004   public int newMethod(
1005       final String owner, final String name, final String descriptor, final boolean isInterface) {
1006     return symbolTable.addConstantMethodref(owner, name, descriptor, isInterface).index;
1007   }
1008 
1009   /**
1010    * Adds a name and type to the constant pool of the class being build. Does nothing if the
1011    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
1012    * sub classes, and is normally not needed by class generators or adapters.</i>
1013    *
1014    * @param name a name.
1015    * @param descriptor a type descriptor.
1016    * @return the index of a new or already existing name and type item.
1017    */
1018   public int newNameType(final String name, final String descriptor) {
1019     return symbolTable.addConstantNameAndType(name, descriptor);
1020   }
1021 
1022   // -----------------------------------------------------------------------------------------------
1023   // Default method to compute common super classes when computing stack map frames
1024   // -----------------------------------------------------------------------------------------------
1025 
1026   /**
1027    * Returns the common super type of the two given types. The default implementation of this method
1028    * <i>loads</i> the two given classes and uses the java.lang.Class methods to find the common
1029    * super class. It can be overridden to compute this common super type in other ways, in
1030    * particular without actually loading any class, or to take into account the class that is
1031    * currently being generated by this ClassWriter, which can of course not be loaded since it is
1032    * under construction.
1033    *
1034    * @param type1 the internal name of a class (see {@link Type#getInternalName()}).
1035    * @param type2 the internal name of another class (see {@link Type#getInternalName()}).
1036    * @return the internal name of the common super class of the two given classes (see {@link
1037    *     Type#getInternalName()}).
1038    */
1039   protected String getCommonSuperClass(final String type1, final String type2) {
1040     ClassLoader classLoader = getClassLoader();
1041     Class<?> class1;
1042     try {
1043       class1 = Class.forName(type1.replace('/', '.'), false, classLoader);
1044     } catch (ClassNotFoundException e) {
1045       throw new TypeNotPresentException(type1, e);
1046     }
1047     Class<?> class2;
1048     try {
1049       class2 = Class.forName(type2.replace('/', '.'), false, classLoader);
1050     } catch (ClassNotFoundException e) {
1051       throw new TypeNotPresentException(type2, e);
1052     }
1053     if (class1.isAssignableFrom(class2)) {
1054       return type1;
1055     }
1056     if (class2.isAssignableFrom(class1)) {
1057       return type2;
1058     }
1059     if (class1.isInterface() || class2.isInterface()) {
1060       return "java/lang/Object";
1061     } else {
1062       do {
1063         class1 = class1.getSuperclass();
1064       } while (!class1.isAssignableFrom(class2));
1065       return class1.getName().replace('.', '/');
1066     }
1067   }
1068 
1069   /**
1070    * Returns the {@link ClassLoader} to be used by the default implementation of {@link
1071    * #getCommonSuperClass(String, String)}, that of this {@link ClassWriter}'s runtime type by
1072    * default.
1073    *
1074    * @return ClassLoader
1075    */
1076   protected ClassLoader getClassLoader() {
1077     return getClass().getClassLoader();
1078   }
1079 }
1080