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