001// ASM: a very small and fast Java bytecode manipulation framework
002// Copyright (c) 2000-2011 INRIA, France Telecom
003// All rights reserved.
004//
005// Redistribution and use in source and binary forms, with or without
006// modification, are permitted provided that the following conditions
007// are met:
008// 1. Redistributions of source code must retain the above copyright
009//    notice, this list of conditions and the following disclaimer.
010// 2. Redistributions in binary form must reproduce the above copyright
011//    notice, this list of conditions and the following disclaimer in the
012//    documentation and/or other materials provided with the distribution.
013// 3. Neither the name of the copyright holders nor the names of its
014//    contributors may be used to endorse or promote products derived from
015//    this software without specific prior written permission.
016//
017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
027// THE POSSIBILITY OF SUCH DAMAGE.
028package io.ebean.enhance.asm;
029
030/**
031 * A {@link ClassVisitor} that generates a corresponding ClassFile structure, as defined in the Java
032 * Virtual Machine Specification (JVMS). It can be used alone, to generate a Java class "from
033 * scratch", or with one or more {@link ClassReader} and adapter {@link ClassVisitor} to generate a
034 * modified class from one or more existing Java classes.
035 *
036 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a>
037 * @author Eric Bruneton
038 */
039public class ClassWriter extends ClassVisitor {
040
041  /**
042   * A flag to automatically compute the maximum stack size and the maximum number of local
043   * variables of methods. If this flag is set, then the arguments of the {@link
044   * MethodVisitor#visitMaxs} method of the {@link MethodVisitor} returned by the {@link
045   * #visitMethod} method will be ignored, and computed automatically from the signature and the
046   * bytecode of each method.
047   *
048   * <p><b>Note:</b> for classes whose version is {@link Opcodes#V1_7} of more, this option requires
049   * valid stack map frames. The maximum stack size is then computed from these frames, and from the
050   * bytecode instructions in between. If stack map frames are not present or must be recomputed,
051   * used {@link #COMPUTE_FRAMES} instead.
052   *
053   * @see #ClassWriter(int)
054   */
055  public static final int COMPUTE_MAXS = 1;
056
057  /**
058   * A flag to automatically compute the stack map frames of methods from scratch. If this flag is
059   * set, then the calls to the {@link MethodVisitor#visitFrame} method are ignored, and the stack
060   * map frames are recomputed from the methods bytecode. The arguments of the {@link
061   * MethodVisitor#visitMaxs} method are also ignored and recomputed from the bytecode. In other
062   * words, {@link #COMPUTE_FRAMES} implies {@link #COMPUTE_MAXS}.
063   *
064   * @see #ClassWriter(int)
065   */
066  public static final int COMPUTE_FRAMES = 2;
067
068  /**
069   * The flags passed to the constructor. Must be zero or more of {@link #COMPUTE_MAXS} and {@link
070   * #COMPUTE_FRAMES}.
071   */
072  private final int flags;
073
074  // Note: fields are ordered as in the ClassFile structure, and those related to attributes are
075  // ordered as in Section 4.7 of the JVMS.
076
077  /**
078   * The minor_version and major_version fields of the JVMS ClassFile structure. minor_version is
079   * stored in the 16 most significant bits, and major_version in the 16 least significant bits.
080   */
081  private int version;
082
083  /** The symbol table for this class (contains the constant_pool and the BootstrapMethods). */
084  private final SymbolTable symbolTable;
085
086  /**
087   * The access_flags field of the JVMS ClassFile structure. This field can contain ASM specific
088   * access flags, such as {@link Opcodes#ACC_DEPRECATED} or {@link Opcodes#ACC_RECORD}, which are
089   * removed when generating the ClassFile structure.
090   */
091  private int accessFlags;
092
093  /** The this_class field of the JVMS ClassFile structure. */
094  private int thisClass;
095
096  /** The super_class field of the JVMS ClassFile structure. */
097  private int superClass;
098
099  /** 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   */
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   */
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   */
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
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
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
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
343  public final void visitNestHost(final String nestHost) {
344    nestHostClassIndex = symbolTable.addConstantClass(nestHost).index;
345  }
346
347  @Override
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
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
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
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
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
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
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
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
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
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
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   */
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}