• 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_MAX_STACK_AND_LOCAL_FROM_FRAMES}, {@link
221    * MethodWriter#COMPUTE_INSERTED_FRAMES}, or {@link MethodWriter#COMPUTE_ALL_FRAMES}.
222    */
223   private int compute;
224 
225   // -----------------------------------------------------------------------------------------------
226   // Constructor
227   // -----------------------------------------------------------------------------------------------
228 
229   /**
230    * Constructs a new {@link ClassWriter} object.
231    *
232    * @param flags option flags that can be used to modify the default behavior of this class. Must
233    *     be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}.
234    */
ClassWriter(final int flags)235   public ClassWriter(final int flags) {
236     this(null, flags);
237   }
238 
239   /**
240    * Constructs a new {@link ClassWriter} object and enables optimizations for "mostly add" bytecode
241    * transformations. These optimizations are the following:
242    *
243    * <ul>
244    *   <li>The constant pool and bootstrap methods from the original class are copied as is in the
245    *       new class, which saves time. New constant pool entries and new bootstrap methods will be
246    *       added at the end if necessary, but unused constant pool entries or bootstrap methods
247    *       <i>won't be removed</i>.
248    *   <li>Methods that are not transformed are copied as is in the new class, directly from the
249    *       original class bytecode (i.e. without emitting visit events for all the method
250    *       instructions), which saves a <i>lot</i> of time. Untransformed methods are detected by
251    *       the fact that the {@link ClassReader} receives {@link MethodVisitor} objects that come
252    *       from a {@link ClassWriter} (and not from any other {@link ClassVisitor} instance).
253    * </ul>
254    *
255    * @param classReader the {@link ClassReader} used to read the original class. It will be used to
256    *     copy the entire constant pool and bootstrap methods from the original class and also to
257    *     copy other fragments of original bytecode where applicable.
258    * @param flags option flags that can be used to modify the default behavior of this class. Must
259    *     be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. <i>These option flags
260    *     do not affect methods that are copied as is in the new class. This means that neither the
261    *     maximum stack size nor the stack frames will be computed for these methods</i>.
262    */
ClassWriter(final ClassReader classReader, final int flags)263   public ClassWriter(final ClassReader classReader, final int flags) {
264     super(/* latest api = */ Opcodes.ASM9);
265     this.flags = flags;
266     symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader);
267     if ((flags & COMPUTE_FRAMES) != 0) {
268       compute = MethodWriter.COMPUTE_ALL_FRAMES;
269     } else if ((flags & COMPUTE_MAXS) != 0) {
270       compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL;
271     } else {
272       compute = MethodWriter.COMPUTE_NOTHING;
273     }
274   }
275 
276   // -----------------------------------------------------------------------------------------------
277   // Accessors
278   // -----------------------------------------------------------------------------------------------
279 
280   /**
281    * Returns true if all the given flags were passed to the constructor.
282    *
283    * @param flags some option flags. Must be zero or more of {@link #COMPUTE_MAXS} and {@link
284    *     #COMPUTE_FRAMES}.
285    * @return true if all the given flags, or more, were passed to the constructor.
286    */
hasFlags(final int flags)287   public boolean hasFlags(final int flags) {
288     return (this.flags & flags) == flags;
289   }
290 
291   // -----------------------------------------------------------------------------------------------
292   // Implementation of the ClassVisitor abstract class
293   // -----------------------------------------------------------------------------------------------
294 
295   @Override
visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)296   public final void visit(
297       final int version,
298       final int access,
299       final String name,
300       final String signature,
301       final String superName,
302       final String[] interfaces) {
303     this.version = version;
304     this.accessFlags = access;
305     this.thisClass = symbolTable.setMajorVersionAndClassName(version & 0xFFFF, name);
306     if (signature != null) {
307       this.signatureIndex = symbolTable.addConstantUtf8(signature);
308     }
309     this.superClass = superName == null ? 0 : symbolTable.addConstantClass(superName).index;
310     if (interfaces != null && interfaces.length > 0) {
311       interfaceCount = interfaces.length;
312       this.interfaces = new int[interfaceCount];
313       for (int i = 0; i < interfaceCount; ++i) {
314         this.interfaces[i] = symbolTable.addConstantClass(interfaces[i]).index;
315       }
316     }
317     if (compute == MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL && (version & 0xFFFF) >= Opcodes.V1_7) {
318       compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES;
319     }
320   }
321 
322   @Override
visitSource(final String file, final String debug)323   public final void visitSource(final String file, final String debug) {
324     if (file != null) {
325       sourceFileIndex = symbolTable.addConstantUtf8(file);
326     }
327     if (debug != null) {
328       debugExtension = new ByteVector().encodeUtf8(debug, 0, Integer.MAX_VALUE);
329     }
330   }
331 
332   @Override
visitModule( final String name, final int access, final String version)333   public final ModuleVisitor visitModule(
334       final String name, final int access, final String version) {
335     return moduleWriter =
336         new ModuleWriter(
337             symbolTable,
338             symbolTable.addConstantModule(name).index,
339             access,
340             version == null ? 0 : symbolTable.addConstantUtf8(version));
341   }
342 
343   @Override
visitNestHost(final String nestHost)344   public final void visitNestHost(final String nestHost) {
345     nestHostClassIndex = symbolTable.addConstantClass(nestHost).index;
346   }
347 
348   @Override
visitOuterClass( final String owner, final String name, final String descriptor)349   public final void visitOuterClass(
350       final String owner, final String name, final String descriptor) {
351     enclosingClassIndex = symbolTable.addConstantClass(owner).index;
352     if (name != null && descriptor != null) {
353       enclosingMethodIndex = symbolTable.addConstantNameAndType(name, descriptor);
354     }
355   }
356 
357   @Override
visitAnnotation(final String descriptor, final boolean visible)358   public final AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
359     if (visible) {
360       return lastRuntimeVisibleAnnotation =
361           AnnotationWriter.create(symbolTable, descriptor, lastRuntimeVisibleAnnotation);
362     } else {
363       return lastRuntimeInvisibleAnnotation =
364           AnnotationWriter.create(symbolTable, descriptor, lastRuntimeInvisibleAnnotation);
365     }
366   }
367 
368   @Override
visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)369   public final AnnotationVisitor visitTypeAnnotation(
370       final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
371     if (visible) {
372       return lastRuntimeVisibleTypeAnnotation =
373           AnnotationWriter.create(
374               symbolTable, typeRef, typePath, descriptor, lastRuntimeVisibleTypeAnnotation);
375     } else {
376       return lastRuntimeInvisibleTypeAnnotation =
377           AnnotationWriter.create(
378               symbolTable, typeRef, typePath, descriptor, lastRuntimeInvisibleTypeAnnotation);
379     }
380   }
381 
382   @Override
visitAttribute(final Attribute attribute)383   public final void visitAttribute(final Attribute attribute) {
384     // Store the attributes in the <i>reverse</i> order of their visit by this method.
385     attribute.nextAttribute = firstAttribute;
386     firstAttribute = attribute;
387   }
388 
389   @Override
visitNestMember(final String nestMember)390   public final void visitNestMember(final String nestMember) {
391     if (nestMemberClasses == null) {
392       nestMemberClasses = new ByteVector();
393     }
394     ++numberOfNestMemberClasses;
395     nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index);
396   }
397 
398   @Override
visitPermittedSubclass(final String permittedSubclass)399   public final void visitPermittedSubclass(final String permittedSubclass) {
400     if (permittedSubclasses == null) {
401       permittedSubclasses = new ByteVector();
402     }
403     ++numberOfPermittedSubclasses;
404     permittedSubclasses.putShort(symbolTable.addConstantClass(permittedSubclass).index);
405   }
406 
407   @Override
visitInnerClass( final String name, final String outerName, final String innerName, final int access)408   public final void visitInnerClass(
409       final String name, final String outerName, final String innerName, final int access) {
410     if (innerClasses == null) {
411       innerClasses = new ByteVector();
412     }
413     // Section 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the constant_pool table
414     // which represents a class or interface C that is not a package member must have exactly one
415     // corresponding entry in the classes array". To avoid duplicates we keep track in the info
416     // field of the Symbol of each CONSTANT_Class_info entry C whether an inner class entry has
417     // already been added for C. If so, we store the index of this inner class entry (plus one) in
418     // the info field. This trick allows duplicate detection in O(1) time.
419     Symbol nameSymbol = symbolTable.addConstantClass(name);
420     if (nameSymbol.info == 0) {
421       ++numberOfInnerClasses;
422       innerClasses.putShort(nameSymbol.index);
423       innerClasses.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index);
424       innerClasses.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName));
425       innerClasses.putShort(access);
426       nameSymbol.info = numberOfInnerClasses;
427     }
428     // Else, compare the inner classes entry nameSymbol.info - 1 with the arguments of this method
429     // and throw an exception if there is a difference?
430   }
431 
432   @Override
visitRecordComponent( final String name, final String descriptor, final String signature)433   public final RecordComponentVisitor visitRecordComponent(
434       final String name, final String descriptor, final String signature) {
435     RecordComponentWriter recordComponentWriter =
436         new RecordComponentWriter(symbolTable, name, descriptor, signature);
437     if (firstRecordComponent == null) {
438       firstRecordComponent = recordComponentWriter;
439     } else {
440       lastRecordComponent.delegate = recordComponentWriter;
441     }
442     return lastRecordComponent = recordComponentWriter;
443   }
444 
445   @Override
visitField( final int access, final String name, final String descriptor, final String signature, final Object value)446   public final FieldVisitor visitField(
447       final int access,
448       final String name,
449       final String descriptor,
450       final String signature,
451       final Object value) {
452     FieldWriter fieldWriter =
453         new FieldWriter(symbolTable, access, name, descriptor, signature, value);
454     if (firstField == null) {
455       firstField = fieldWriter;
456     } else {
457       lastField.fv = fieldWriter;
458     }
459     return lastField = fieldWriter;
460   }
461 
462   @Override
visitMethod( final int access, final String name, final String descriptor, final String signature, final String[] exceptions)463   public final MethodVisitor visitMethod(
464       final int access,
465       final String name,
466       final String descriptor,
467       final String signature,
468       final String[] exceptions) {
469     MethodWriter methodWriter =
470         new MethodWriter(symbolTable, access, name, descriptor, signature, exceptions, compute);
471     if (firstMethod == null) {
472       firstMethod = methodWriter;
473     } else {
474       lastMethod.mv = methodWriter;
475     }
476     return lastMethod = methodWriter;
477   }
478 
479   @Override
visitEnd()480   public final void visitEnd() {
481     // Nothing to do.
482   }
483 
484   // -----------------------------------------------------------------------------------------------
485   // Other public methods
486   // -----------------------------------------------------------------------------------------------
487 
488   /**
489    * Returns the content of the class file that was built by this ClassWriter.
490    *
491    * @return the binary content of the JVMS ClassFile structure that was built by this ClassWriter.
492    * @throws ClassTooLargeException if the constant pool of the class is too large.
493    * @throws MethodTooLargeException if the Code attribute of a method is too large.
494    */
toByteArray()495   public byte[] toByteArray() {
496     // First step: compute the size in bytes of the ClassFile structure.
497     // The magic field uses 4 bytes, 10 mandatory fields (minor_version, major_version,
498     // constant_pool_count, access_flags, this_class, super_class, interfaces_count, fields_count,
499     // methods_count and attributes_count) use 2 bytes each, and each interface uses 2 bytes too.
500     int size = 24 + 2 * interfaceCount;
501     int fieldsCount = 0;
502     FieldWriter fieldWriter = firstField;
503     while (fieldWriter != null) {
504       ++fieldsCount;
505       size += fieldWriter.computeFieldInfoSize();
506       fieldWriter = (FieldWriter) fieldWriter.fv;
507     }
508     int methodsCount = 0;
509     MethodWriter methodWriter = firstMethod;
510     while (methodWriter != null) {
511       ++methodsCount;
512       size += methodWriter.computeMethodInfoSize();
513       methodWriter = (MethodWriter) methodWriter.mv;
514     }
515 
516     // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
517     int attributesCount = 0;
518     if (innerClasses != null) {
519       ++attributesCount;
520       size += 8 + innerClasses.length;
521       symbolTable.addConstantUtf8(Constants.INNER_CLASSES);
522     }
523     if (enclosingClassIndex != 0) {
524       ++attributesCount;
525       size += 10;
526       symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD);
527     }
528     if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) {
529       ++attributesCount;
530       size += 6;
531       symbolTable.addConstantUtf8(Constants.SYNTHETIC);
532     }
533     if (signatureIndex != 0) {
534       ++attributesCount;
535       size += 8;
536       symbolTable.addConstantUtf8(Constants.SIGNATURE);
537     }
538     if (sourceFileIndex != 0) {
539       ++attributesCount;
540       size += 8;
541       symbolTable.addConstantUtf8(Constants.SOURCE_FILE);
542     }
543     if (debugExtension != null) {
544       ++attributesCount;
545       size += 6 + debugExtension.length;
546       symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION);
547     }
548     if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
549       ++attributesCount;
550       size += 6;
551       symbolTable.addConstantUtf8(Constants.DEPRECATED);
552     }
553     if (lastRuntimeVisibleAnnotation != null) {
554       ++attributesCount;
555       size +=
556           lastRuntimeVisibleAnnotation.computeAnnotationsSize(
557               Constants.RUNTIME_VISIBLE_ANNOTATIONS);
558     }
559     if (lastRuntimeInvisibleAnnotation != null) {
560       ++attributesCount;
561       size +=
562           lastRuntimeInvisibleAnnotation.computeAnnotationsSize(
563               Constants.RUNTIME_INVISIBLE_ANNOTATIONS);
564     }
565     if (lastRuntimeVisibleTypeAnnotation != null) {
566       ++attributesCount;
567       size +=
568           lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize(
569               Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
570     }
571     if (lastRuntimeInvisibleTypeAnnotation != null) {
572       ++attributesCount;
573       size +=
574           lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize(
575               Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS);
576     }
577     if (symbolTable.computeBootstrapMethodsSize() > 0) {
578       ++attributesCount;
579       size += symbolTable.computeBootstrapMethodsSize();
580     }
581     if (moduleWriter != null) {
582       attributesCount += moduleWriter.getAttributeCount();
583       size += moduleWriter.computeAttributesSize();
584     }
585     if (nestHostClassIndex != 0) {
586       ++attributesCount;
587       size += 8;
588       symbolTable.addConstantUtf8(Constants.NEST_HOST);
589     }
590     if (nestMemberClasses != null) {
591       ++attributesCount;
592       size += 8 + nestMemberClasses.length;
593       symbolTable.addConstantUtf8(Constants.NEST_MEMBERS);
594     }
595     if (permittedSubclasses != null) {
596       ++attributesCount;
597       size += 8 + permittedSubclasses.length;
598       symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES);
599     }
600     int recordComponentCount = 0;
601     int recordSize = 0;
602     if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) {
603       RecordComponentWriter recordComponentWriter = firstRecordComponent;
604       while (recordComponentWriter != null) {
605         ++recordComponentCount;
606         recordSize += recordComponentWriter.computeRecordComponentInfoSize();
607         recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
608       }
609       ++attributesCount;
610       size += 8 + recordSize;
611       symbolTable.addConstantUtf8(Constants.RECORD);
612     }
613     if (firstAttribute != null) {
614       attributesCount += firstAttribute.getAttributeCount();
615       size += firstAttribute.computeAttributesSize(symbolTable);
616     }
617     // IMPORTANT: this must be the last part of the ClassFile size computation, because the previous
618     // statements can add attribute names to the constant pool, thereby changing its size!
619     size += symbolTable.getConstantPoolLength();
620     int constantPoolCount = symbolTable.getConstantPoolCount();
621     if (constantPoolCount > 0xFFFF) {
622       throw new ClassTooLargeException(symbolTable.getClassName(), constantPoolCount);
623     }
624 
625     // Second step: allocate a ByteVector of the correct size (in order to avoid any array copy in
626     // dynamic resizes) and fill it with the ClassFile content.
627     ByteVector result = new ByteVector(size);
628     result.putInt(0xCAFEBABE).putInt(version);
629     symbolTable.putConstantPool(result);
630     int mask = (version & 0xFFFF) < Opcodes.V1_5 ? Opcodes.ACC_SYNTHETIC : 0;
631     result.putShort(accessFlags & ~mask).putShort(thisClass).putShort(superClass);
632     result.putShort(interfaceCount);
633     for (int i = 0; i < interfaceCount; ++i) {
634       result.putShort(interfaces[i]);
635     }
636     result.putShort(fieldsCount);
637     fieldWriter = firstField;
638     while (fieldWriter != null) {
639       fieldWriter.putFieldInfo(result);
640       fieldWriter = (FieldWriter) fieldWriter.fv;
641     }
642     result.putShort(methodsCount);
643     boolean hasFrames = false;
644     boolean hasAsmInstructions = false;
645     methodWriter = firstMethod;
646     while (methodWriter != null) {
647       hasFrames |= methodWriter.hasFrames();
648       hasAsmInstructions |= methodWriter.hasAsmInstructions();
649       methodWriter.putMethodInfo(result);
650       methodWriter = (MethodWriter) methodWriter.mv;
651     }
652     // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
653     result.putShort(attributesCount);
654     if (innerClasses != null) {
655       result
656           .putShort(symbolTable.addConstantUtf8(Constants.INNER_CLASSES))
657           .putInt(innerClasses.length + 2)
658           .putShort(numberOfInnerClasses)
659           .putByteArray(innerClasses.data, 0, innerClasses.length);
660     }
661     if (enclosingClassIndex != 0) {
662       result
663           .putShort(symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD))
664           .putInt(4)
665           .putShort(enclosingClassIndex)
666           .putShort(enclosingMethodIndex);
667     }
668     if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) {
669       result.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0);
670     }
671     if (signatureIndex != 0) {
672       result
673           .putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE))
674           .putInt(2)
675           .putShort(signatureIndex);
676     }
677     if (sourceFileIndex != 0) {
678       result
679           .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_FILE))
680           .putInt(2)
681           .putShort(sourceFileIndex);
682     }
683     if (debugExtension != null) {
684       int length = debugExtension.length;
685       result
686           .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION))
687           .putInt(length)
688           .putByteArray(debugExtension.data, 0, length);
689     }
690     if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
691       result.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0);
692     }
693     AnnotationWriter.putAnnotations(
694         symbolTable,
695         lastRuntimeVisibleAnnotation,
696         lastRuntimeInvisibleAnnotation,
697         lastRuntimeVisibleTypeAnnotation,
698         lastRuntimeInvisibleTypeAnnotation,
699         result);
700     symbolTable.putBootstrapMethods(result);
701     if (moduleWriter != null) {
702       moduleWriter.putAttributes(result);
703     }
704     if (nestHostClassIndex != 0) {
705       result
706           .putShort(symbolTable.addConstantUtf8(Constants.NEST_HOST))
707           .putInt(2)
708           .putShort(nestHostClassIndex);
709     }
710     if (nestMemberClasses != null) {
711       result
712           .putShort(symbolTable.addConstantUtf8(Constants.NEST_MEMBERS))
713           .putInt(nestMemberClasses.length + 2)
714           .putShort(numberOfNestMemberClasses)
715           .putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length);
716     }
717     if (permittedSubclasses != null) {
718       result
719           .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES))
720           .putInt(permittedSubclasses.length + 2)
721           .putShort(numberOfPermittedSubclasses)
722           .putByteArray(permittedSubclasses.data, 0, permittedSubclasses.length);
723     }
724     if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) {
725       result
726           .putShort(symbolTable.addConstantUtf8(Constants.RECORD))
727           .putInt(recordSize + 2)
728           .putShort(recordComponentCount);
729       RecordComponentWriter recordComponentWriter = firstRecordComponent;
730       while (recordComponentWriter != null) {
731         recordComponentWriter.putRecordComponentInfo(result);
732         recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
733       }
734     }
735     if (firstAttribute != null) {
736       firstAttribute.putAttributes(symbolTable, result);
737     }
738 
739     // Third step: replace the ASM specific instructions, if any.
740     if (hasAsmInstructions) {
741       return replaceAsmInstructions(result.data, hasFrames);
742     } else {
743       return result.data;
744     }
745   }
746 
747   /**
748    * Returns the equivalent of the given class file, with the ASM specific instructions replaced
749    * with standard ones. This is done with a ClassReader -&gt; ClassWriter round trip.
750    *
751    * @param classFile a class file containing ASM specific instructions, generated by this
752    *     ClassWriter.
753    * @param hasFrames whether there is at least one stack map frames in 'classFile'.
754    * @return an equivalent of 'classFile', with the ASM specific instructions replaced with standard
755    *     ones.
756    */
757   private byte[] replaceAsmInstructions(final byte[] classFile, final boolean hasFrames) {
758     final Attribute[] attributes = getAttributePrototypes();
759     firstField = null;
760     lastField = null;
761     firstMethod = null;
762     lastMethod = null;
763     lastRuntimeVisibleAnnotation = null;
764     lastRuntimeInvisibleAnnotation = null;
765     lastRuntimeVisibleTypeAnnotation = null;
766     lastRuntimeInvisibleTypeAnnotation = null;
767     moduleWriter = null;
768     nestHostClassIndex = 0;
769     numberOfNestMemberClasses = 0;
770     nestMemberClasses = null;
771     numberOfPermittedSubclasses = 0;
772     permittedSubclasses = null;
773     firstRecordComponent = null;
774     lastRecordComponent = null;
775     firstAttribute = null;
776     compute = hasFrames ? MethodWriter.COMPUTE_INSERTED_FRAMES : MethodWriter.COMPUTE_NOTHING;
777     new ClassReader(classFile, 0, /* checkClassVersion = */ false)
778         .accept(
779             this,
780             attributes,
781             (hasFrames ? ClassReader.EXPAND_FRAMES : 0) | ClassReader.EXPAND_ASM_INSNS);
782     return toByteArray();
783   }
784 
785   /**
786    * Returns the prototypes of the attributes used by this class, its fields and its methods.
787    *
788    * @return the prototypes of the attributes used by this class, its fields and its methods.
789    */
790   private Attribute[] getAttributePrototypes() {
791     Attribute.Set attributePrototypes = new Attribute.Set();
792     attributePrototypes.addAttributes(firstAttribute);
793     FieldWriter fieldWriter = firstField;
794     while (fieldWriter != null) {
795       fieldWriter.collectAttributePrototypes(attributePrototypes);
796       fieldWriter = (FieldWriter) fieldWriter.fv;
797     }
798     MethodWriter methodWriter = firstMethod;
799     while (methodWriter != null) {
800       methodWriter.collectAttributePrototypes(attributePrototypes);
801       methodWriter = (MethodWriter) methodWriter.mv;
802     }
803     RecordComponentWriter recordComponentWriter = firstRecordComponent;
804     while (recordComponentWriter != null) {
805       recordComponentWriter.collectAttributePrototypes(attributePrototypes);
806       recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate;
807     }
808     return attributePrototypes.toArray();
809   }
810 
811   // -----------------------------------------------------------------------------------------------
812   // Utility methods: constant pool management for Attribute sub classes
813   // -----------------------------------------------------------------------------------------------
814 
815   /**
816    * Adds a number or string constant to the constant pool of the class being build. Does nothing if
817    * the constant pool already contains a similar item. <i>This method is intended for {@link
818    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
819    *
820    * @param value the value of the constant to be added to the constant pool. This parameter must be
821    *     an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
822    * @return the index of a new or already existing constant item with the given value.
823    */
824   public int newConst(final Object value) {
825     return symbolTable.addConstant(value).index;
826   }
827 
828   /**
829    * Adds an UTF8 string to the constant pool of the class being build. Does nothing if the constant
830    * pool already contains a similar item. <i>This method is intended for {@link Attribute} sub
831    * classes, and is normally not needed by class generators or adapters.</i>
832    *
833    * @param value the String value.
834    * @return the index of a new or already existing UTF8 item.
835    */
836   // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
837   public int newUTF8(final String value) {
838     return symbolTable.addConstantUtf8(value);
839   }
840 
841   /**
842    * Adds a class reference to the constant pool of the class being build. Does nothing if the
843    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
844    * sub classes, and is normally not needed by class generators or adapters.</i>
845    *
846    * @param value the internal name of the class (see {@link Type#getInternalName()}).
847    * @return the index of a new or already existing class reference item.
848    */
849   public int newClass(final String value) {
850     return symbolTable.addConstantClass(value).index;
851   }
852 
853   /**
854    * Adds a method type reference to the constant pool of the class being build. Does nothing if the
855    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
856    * sub classes, and is normally not needed by class generators or adapters.</i>
857    *
858    * @param methodDescriptor method descriptor of the method type.
859    * @return the index of a new or already existing method type reference item.
860    */
861   public int newMethodType(final String methodDescriptor) {
862     return symbolTable.addConstantMethodType(methodDescriptor).index;
863   }
864 
865   /**
866    * Adds a module reference to the constant pool of the class being build. Does nothing if the
867    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
868    * sub classes, and is normally not needed by class generators or adapters.</i>
869    *
870    * @param moduleName name of the module.
871    * @return the index of a new or already existing module reference item.
872    */
873   public int newModule(final String moduleName) {
874     return symbolTable.addConstantModule(moduleName).index;
875   }
876 
877   /**
878    * Adds a package reference to the constant pool of the class being build. Does nothing if the
879    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
880    * sub classes, and is normally not needed by class generators or adapters.</i>
881    *
882    * @param packageName name of the package in its internal form.
883    * @return the index of a new or already existing module reference item.
884    */
885   public int newPackage(final String packageName) {
886     return symbolTable.addConstantPackage(packageName).index;
887   }
888 
889   /**
890    * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool
891    * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes,
892    * and is normally not needed by class generators or adapters.</i>
893    *
894    * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link
895    *     Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
896    *     Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
897    *     {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
898    * @param owner the internal name of the field or method owner class (see {@link
899    *     Type#getInternalName()}).
900    * @param name the name of the field or method.
901    * @param descriptor the descriptor of the field or method.
902    * @return the index of a new or already existing method type reference item.
903    * @deprecated this method is superseded by {@link #newHandle(int, String, String, String,
904    *     boolean)}.
905    */
906   @Deprecated
907   public int newHandle(
908       final int tag, final String owner, final String name, final String descriptor) {
909     return newHandle(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE);
910   }
911 
912   /**
913    * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool
914    * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes,
915    * and is normally not needed by class generators or adapters.</i>
916    *
917    * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link
918    *     Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
919    *     Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
920    *     {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
921    * @param owner the internal name of the field or method owner class (see {@link
922    *     Type#getInternalName()}).
923    * @param name the name of the field or method.
924    * @param descriptor the descriptor of the field or method.
925    * @param isInterface true if the owner is an interface.
926    * @return the index of a new or already existing method type reference item.
927    */
928   public int newHandle(
929       final int tag,
930       final String owner,
931       final String name,
932       final String descriptor,
933       final boolean isInterface) {
934     return symbolTable.addConstantMethodHandle(tag, owner, name, descriptor, isInterface).index;
935   }
936 
937   /**
938    * Adds a dynamic constant reference to the constant pool of the class being build. Does nothing
939    * if the constant pool already contains a similar item. <i>This method is intended for {@link
940    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
941    *
942    * @param name name of the invoked method.
943    * @param descriptor field descriptor of the constant type.
944    * @param bootstrapMethodHandle the bootstrap method.
945    * @param bootstrapMethodArguments the bootstrap method constant arguments.
946    * @return the index of a new or already existing dynamic constant reference item.
947    */
948   public int newConstantDynamic(
949       final String name,
950       final String descriptor,
951       final Handle bootstrapMethodHandle,
952       final Object... bootstrapMethodArguments) {
953     return symbolTable.addConstantDynamic(
954             name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments)
955         .index;
956   }
957 
958   /**
959    * Adds an invokedynamic reference to the constant pool of the class being build. Does nothing if
960    * the constant pool already contains a similar item. <i>This method is intended for {@link
961    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
962    *
963    * @param name name of the invoked method.
964    * @param descriptor descriptor of the invoke method.
965    * @param bootstrapMethodHandle the bootstrap method.
966    * @param bootstrapMethodArguments the bootstrap method constant arguments.
967    * @return the index of a new or already existing invokedynamic reference item.
968    */
969   public int newInvokeDynamic(
970       final String name,
971       final String descriptor,
972       final Handle bootstrapMethodHandle,
973       final Object... bootstrapMethodArguments) {
974     return symbolTable.addConstantInvokeDynamic(
975             name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments)
976         .index;
977   }
978 
979   /**
980    * Adds a field reference to the constant pool of the class being build. Does nothing if the
981    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
982    * sub classes, and is normally not needed by class generators or adapters.</i>
983    *
984    * @param owner the internal name of the field's owner class (see {@link Type#getInternalName()}).
985    * @param name the field's name.
986    * @param descriptor the field's descriptor.
987    * @return the index of a new or already existing field reference item.
988    */
989   public int newField(final String owner, final String name, final String descriptor) {
990     return symbolTable.addConstantFieldref(owner, name, descriptor).index;
991   }
992 
993   /**
994    * Adds a method reference to the constant pool of the class being build. Does nothing if the
995    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
996    * sub classes, and is normally not needed by class generators or adapters.</i>
997    *
998    * @param owner the internal name of the method's owner class (see {@link
999    *     Type#getInternalName()}).
1000    * @param name the method's name.
1001    * @param descriptor the method's descriptor.
1002    * @param isInterface {@literal true} if {@code owner} is an interface.
1003    * @return the index of a new or already existing method reference item.
1004    */
1005   public int newMethod(
1006       final String owner, final String name, final String descriptor, final boolean isInterface) {
1007     return symbolTable.addConstantMethodref(owner, name, descriptor, isInterface).index;
1008   }
1009 
1010   /**
1011    * Adds a name and type to the constant pool of the class being build. Does nothing if the
1012    * constant pool already contains a similar item. <i>This method is intended for {@link Attribute}
1013    * sub classes, and is normally not needed by class generators or adapters.</i>
1014    *
1015    * @param name a name.
1016    * @param descriptor a type descriptor.
1017    * @return the index of a new or already existing name and type item.
1018    */
1019   public int newNameType(final String name, final String descriptor) {
1020     return symbolTable.addConstantNameAndType(name, descriptor);
1021   }
1022 
1023   // -----------------------------------------------------------------------------------------------
1024   // Default method to compute common super classes when computing stack map frames
1025   // -----------------------------------------------------------------------------------------------
1026 
1027   /**
1028    * Returns the common super type of the two given types. The default implementation of this method
1029    * <i>loads</i> the two given classes and uses the java.lang.Class methods to find the common
1030    * super class. It can be overridden to compute this common super type in other ways, in
1031    * particular without actually loading any class, or to take into account the class that is
1032    * currently being generated by this ClassWriter, which can of course not be loaded since it is
1033    * under construction.
1034    *
1035    * @param type1 the internal name of a class (see {@link Type#getInternalName()}).
1036    * @param type2 the internal name of another class (see {@link Type#getInternalName()}).
1037    * @return the internal name of the common super class of the two given classes (see {@link
1038    *     Type#getInternalName()}).
1039    */
1040   protected String getCommonSuperClass(final String type1, final String type2) {
1041     ClassLoader classLoader = getClassLoader();
1042     Class<?> class1;
1043     try {
1044       class1 = Class.forName(type1.replace('/', '.'), false, classLoader);
1045     } catch (ClassNotFoundException e) {
1046       throw new TypeNotPresentException(type1, e);
1047     }
1048     Class<?> class2;
1049     try {
1050       class2 = Class.forName(type2.replace('/', '.'), false, classLoader);
1051     } catch (ClassNotFoundException e) {
1052       throw new TypeNotPresentException(type2, e);
1053     }
1054     if (class1.isAssignableFrom(class2)) {
1055       return type1;
1056     }
1057     if (class2.isAssignableFrom(class1)) {
1058       return type2;
1059     }
1060     if (class1.isInterface() || class2.isInterface()) {
1061       return "java/lang/Object";
1062     } else {
1063       do {
1064         class1 = class1.getSuperclass();
1065       } while (!class1.isAssignableFrom(class2));
1066       return class1.getName().replace('.', '/');
1067     }
1068   }
1069 
1070   /**
1071    * Returns the {@link ClassLoader} to be used by the default implementation of {@link
1072    * #getCommonSuperClass(String, String)}, that of this {@link ClassWriter}'s runtime type by
1073    * default.
1074    *
1075    * @return ClassLoader
1076    */
1077   protected ClassLoader getClassLoader() {
1078     return getClass().getClassLoader();
1079   }
1080 }
1081