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
030import java.io.ByteArrayOutputStream;
031import java.io.IOException;
032import java.io.InputStream;
033
034/**
035 * A parser to make a {@link ClassVisitor} visit a ClassFile structure, as defined in the Java
036 * Virtual Machine Specification (JVMS). This class parses the ClassFile content and calls the
037 * appropriate visit methods of a given {@link ClassVisitor} for each field, method and bytecode
038 * instruction encountered.
039 *
040 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a>
041 * @author Eric Bruneton
042 * @author Eugene Kuleshov
043 */
044public class ClassReader {
045
046  /**
047   * A flag to skip the Code attributes. If this flag is set the Code attributes are neither parsed
048   * nor visited.
049   */
050  public static final int SKIP_CODE = 1;
051
052  /**
053   * A flag to skip the SourceFile, SourceDebugExtension, LocalVariableTable, LocalVariableTypeTable
054   * and LineNumberTable attributes. If this flag is set these attributes are neither parsed nor
055   * visited (i.e. {@link ClassVisitor#visitSource}, {@link MethodVisitor#visitLocalVariable} and
056   * {@link MethodVisitor#visitLineNumber} are not called).
057   */
058  public static final int SKIP_DEBUG = 2;
059
060  /**
061   * A flag to skip the StackMap and StackMapTable attributes. If this flag is set these attributes
062   * are neither parsed nor visited (i.e. {@link MethodVisitor#visitFrame} is not called). This flag
063   * is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is used: it avoids visiting frames
064   * that will be ignored and recomputed from scratch.
065   */
066  public static final int SKIP_FRAMES = 4;
067
068  /**
069   * A flag to expand the stack map frames. By default stack map frames are visited in their
070   * original format (i.e. "expanded" for classes whose version is less than V1_6, and "compressed"
071   * for the other classes). If this flag is set, stack map frames are always visited in expanded
072   * format (this option adds a decompression/compression step in ClassReader and ClassWriter which
073   * degrades performance quite a lot).
074   */
075  public static final int EXPAND_FRAMES = 8;
076
077  /**
078   * A flag to expand the ASM specific instructions into an equivalent sequence of standard bytecode
079   * instructions. When resolving a forward jump it may happen that the signed 2 bytes offset
080   * reserved for it is not sufficient to store the bytecode offset. In this case the jump
081   * instruction is replaced with a temporary ASM specific instruction using an unsigned 2 bytes
082   * offset (see {@link Label#resolve}). This internal flag is used to re-read classes containing
083   * such instructions, in order to replace them with standard instructions. In addition, when this
084   * flag is used, goto_w and jsr_w are <i>not</i> converted into goto and jsr, to make sure that
085   * infinite loops where a goto_w is replaced with a goto in ClassReader and converted back to a
086   * goto_w in ClassWriter cannot occur.
087   */
088  static final int EXPAND_ASM_INSNS = 256;
089
090  /** The size of the temporary byte array used to read class input streams chunk by chunk. */
091  private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;
092
093  /**
094   * A byte array containing the JVMS ClassFile structure to be parsed.
095   *
096   * @deprecated Use {@link #readByte(int)} and the other read methods instead. This field will
097   *     eventually be deleted.
098   */
099  @Deprecated
100  // DontCheck(MemberName): can't be renamed (for backward binary compatibility).
101  public final byte[] b;
102
103  /**
104   * A byte array containing the JVMS ClassFile structure to be parsed. <i>The content of this array
105   * must not be modified. This field is intended for {@link Attribute} sub classes, and is normally
106   * not needed by class visitors.</i>
107   *
108   * <p>NOTE: the ClassFile structure can start at any offset within this array, i.e. it does not
109   * necessarily start at offset 0. Use {@link #getItem} and {@link #header} to get correct
110   * ClassFile element offsets within this byte array.
111   */
112  final byte[] classFileBuffer;
113
114  /**
115   * The offset in bytes, in {@link #classFileBuffer}, of each cp_info entry of the ClassFile's
116   * constant_pool array, <i>plus one</i>. In other words, the offset of constant pool entry i is
117   * given by cpInfoOffsets[i] - 1, i.e. its cp_info's tag field is given by b[cpInfoOffsets[i] -
118   * 1].
119   */
120  private final int[] cpInfoOffsets;
121
122  /**
123   * The String objects corresponding to the CONSTANT_Utf8 constant pool items. This cache avoids
124   * multiple parsing of a given CONSTANT_Utf8 constant pool item.
125   */
126  private final String[] constantUtf8Values;
127
128  /**
129   * The ConstantDynamic objects corresponding to the CONSTANT_Dynamic constant pool items. This
130   * cache avoids multiple parsing of a given CONSTANT_Dynamic constant pool item.
131   */
132  private final ConstantDynamic[] constantDynamicValues;
133
134  /**
135   * The start offsets in {@link #classFileBuffer} of each element of the bootstrap_methods array
136   * (in the BootstrapMethods attribute).
137   *
138   * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
139   *     4.7.23</a>
140   */
141  private final int[] bootstrapMethodOffsets;
142
143  /**
144   * A conservative estimate of the maximum length of the strings contained in the constant pool of
145   * the class.
146   */
147  private final int maxStringLength;
148
149  /** The offset in bytes of the ClassFile's access_flags field. */
150  public final int header;
151
152  // -----------------------------------------------------------------------------------------------
153  // Constructors
154  // -----------------------------------------------------------------------------------------------
155
156  /**
157   * Constructs a new {@link ClassReader} object.
158   *
159   * @param classFile the JVMS ClassFile structure to be read.
160   */
161  public ClassReader(final byte[] classFile) {
162    this(classFile, 0, classFile.length);
163  }
164
165  /**
166   * Constructs a new {@link ClassReader} object.
167   *
168   * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.
169   * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.
170   * @param classFileLength the length in bytes of the ClassFile to be read.
171   */
172  public ClassReader(
173      final byte[] classFileBuffer,
174      final int classFileOffset,
175      final int classFileLength) { // NOPMD(UnusedFormalParameter) used for backward compatibility.
176    this(classFileBuffer, classFileOffset, /* checkClassVersion = */ true);
177  }
178
179  /**
180   * Constructs a new {@link ClassReader} object. <i>This internal constructor must not be exposed
181   * as a public API</i>.
182   *
183   * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.
184   * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.
185   * @param checkClassVersion whether to check the class version or not.
186   */
187  ClassReader(
188      final byte[] classFileBuffer, final int classFileOffset, final boolean checkClassVersion) {
189    this.classFileBuffer = classFileBuffer;
190    this.b = classFileBuffer;
191    // Check the class' major_version. This field is after the magic and minor_version fields, which
192    // use 4 and 2 bytes respectively.
193    if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V13) {
194      throw new IllegalArgumentException(
195          "Unsupported class file major version " + readShort(classFileOffset + 6));
196    }
197    // Create the constant pool arrays. The constant_pool_count field is after the magic,
198    // minor_version and major_version fields, which use 4, 2 and 2 bytes respectively.
199    int constantPoolCount = readUnsignedShort(classFileOffset + 8);
200    cpInfoOffsets = new int[constantPoolCount];
201    constantUtf8Values = new String[constantPoolCount];
202    // Compute the offset of each constant pool entry, as well as a conservative estimate of the
203    // maximum length of the constant pool strings. The first constant pool entry is after the
204    // magic, minor_version, major_version and constant_pool_count fields, which use 4, 2, 2 and 2
205    // bytes respectively.
206    int currentCpInfoIndex = 1;
207    int currentCpInfoOffset = classFileOffset + 10;
208    int currentMaxStringLength = 0;
209    boolean hasBootstrapMethods = false;
210    boolean hasConstantDynamic = false;
211    // The offset of the other entries depend on the total size of all the previous entries.
212    while (currentCpInfoIndex < constantPoolCount) {
213      cpInfoOffsets[currentCpInfoIndex++] = currentCpInfoOffset + 1;
214      int cpInfoSize;
215      switch (classFileBuffer[currentCpInfoOffset]) {
216        case Symbol.CONSTANT_FIELDREF_TAG:
217        case Symbol.CONSTANT_METHODREF_TAG:
218        case Symbol.CONSTANT_INTERFACE_METHODREF_TAG:
219        case Symbol.CONSTANT_INTEGER_TAG:
220        case Symbol.CONSTANT_FLOAT_TAG:
221        case Symbol.CONSTANT_NAME_AND_TYPE_TAG:
222          cpInfoSize = 5;
223          break;
224        case Symbol.CONSTANT_DYNAMIC_TAG:
225          cpInfoSize = 5;
226          hasBootstrapMethods = true;
227          hasConstantDynamic = true;
228          break;
229        case Symbol.CONSTANT_INVOKE_DYNAMIC_TAG:
230          cpInfoSize = 5;
231          hasBootstrapMethods = true;
232          break;
233        case Symbol.CONSTANT_LONG_TAG:
234        case Symbol.CONSTANT_DOUBLE_TAG:
235          cpInfoSize = 9;
236          currentCpInfoIndex++;
237          break;
238        case Symbol.CONSTANT_UTF8_TAG:
239          cpInfoSize = 3 + readUnsignedShort(currentCpInfoOffset + 1);
240          if (cpInfoSize > currentMaxStringLength) {
241            // The size in bytes of this CONSTANT_Utf8 structure provides a conservative estimate
242            // of the length in characters of the corresponding string, and is much cheaper to
243            // compute than this exact length.
244            currentMaxStringLength = cpInfoSize;
245          }
246          break;
247        case Symbol.CONSTANT_METHOD_HANDLE_TAG:
248          cpInfoSize = 4;
249          break;
250        case Symbol.CONSTANT_CLASS_TAG:
251        case Symbol.CONSTANT_STRING_TAG:
252        case Symbol.CONSTANT_METHOD_TYPE_TAG:
253        case Symbol.CONSTANT_PACKAGE_TAG:
254        case Symbol.CONSTANT_MODULE_TAG:
255          cpInfoSize = 3;
256          break;
257        default:
258          throw new IllegalArgumentException();
259      }
260      currentCpInfoOffset += cpInfoSize;
261    }
262    maxStringLength = currentMaxStringLength;
263    // The Classfile's access_flags field is just after the last constant pool entry.
264    header = currentCpInfoOffset;
265
266    // Allocate the cache of ConstantDynamic values, if there is at least one.
267    constantDynamicValues = hasConstantDynamic ? new ConstantDynamic[constantPoolCount] : null;
268
269    // Read the BootstrapMethods attribute, if any (only get the offset of each method).
270    bootstrapMethodOffsets =
271        hasBootstrapMethods ? readBootstrapMethodsAttribute(currentMaxStringLength) : null;
272  }
273
274  /**
275   * Constructs a new {@link ClassReader} object.
276   *
277   * @param inputStream an input stream of the JVMS ClassFile structure to be read. This input
278   *     stream must contain nothing more than the ClassFile structure itself. It is read from its
279   *     current position to its end.
280   * @throws IOException if a problem occurs during reading.
281   */
282  public ClassReader(final InputStream inputStream) throws IOException {
283    this(readStream(inputStream, false));
284  }
285
286  /**
287   * Constructs a new {@link ClassReader} object.
288   *
289   * @param className the fully qualified name of the class to be read. The ClassFile structure is
290   *     retrieved with the current class loader's {@link ClassLoader#getSystemResourceAsStream}.
291   * @throws IOException if an exception occurs during reading.
292   */
293  public ClassReader(final String className) throws IOException {
294    this(
295        readStream(
296            ClassLoader.getSystemResourceAsStream(className.replace('.', '/') + ".class"), true));
297  }
298
299  /**
300   * Reads the given input stream and returns its content as a byte array.
301   *
302   * @param inputStream an input stream.
303   * @param close true to close the input stream after reading.
304   * @return the content of the given input stream.
305   * @throws IOException if a problem occurs during reading.
306   */
307  private static byte[] readStream(final InputStream inputStream, final boolean close)
308      throws IOException {
309    if (inputStream == null) {
310      throw new IOException("Class not found");
311    }
312    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
313      byte[] data = new byte[INPUT_STREAM_DATA_CHUNK_SIZE];
314      int bytesRead;
315      while ((bytesRead = inputStream.read(data, 0, data.length)) != -1) {
316        outputStream.write(data, 0, bytesRead);
317      }
318      outputStream.flush();
319      return outputStream.toByteArray();
320    } finally {
321      if (close) {
322        inputStream.close();
323      }
324    }
325  }
326
327  // -----------------------------------------------------------------------------------------------
328  // Accessors
329  // -----------------------------------------------------------------------------------------------
330
331  /**
332   * Returns the class's access flags (see {@link Opcodes}). This value may not reflect Deprecated
333   * and Synthetic flags when bytecode is before 1.5 and those flags are represented by attributes.
334   *
335   * @return the class access flags.
336   * @see ClassVisitor#visit(int, int, String, String, String, String[])
337   */
338  public int getAccess() {
339    return readUnsignedShort(header);
340  }
341
342  /**
343   * Returns the internal name of the class (see {@link Type#getInternalName()}).
344   *
345   * @return the internal class name.
346   * @see ClassVisitor#visit(int, int, String, String, String, String[])
347   */
348  public String getClassName() {
349    // this_class is just after the access_flags field (using 2 bytes).
350    return readClass(header + 2, new char[maxStringLength]);
351  }
352
353  /**
354   * Returns the internal of name of the super class (see {@link Type#getInternalName()}). For
355   * interfaces, the super class is {@link Object}.
356   *
357   * @return the internal name of the super class, or {@literal null} for {@link Object} class.
358   * @see ClassVisitor#visit(int, int, String, String, String, String[])
359   */
360  public String getSuperName() {
361    // super_class is after the access_flags and this_class fields (2 bytes each).
362    return readClass(header + 4, new char[maxStringLength]);
363  }
364
365  /**
366   * Returns the internal names of the implemented interfaces (see {@link Type#getInternalName()}).
367   *
368   * @return the internal names of the directly implemented interfaces. Inherited implemented
369   *     interfaces are not returned.
370   * @see ClassVisitor#visit(int, int, String, String, String, String[])
371   */
372  public String[] getInterfaces() {
373    // interfaces_count is after the access_flags, this_class and super_class fields (2 bytes each).
374    int currentOffset = header + 6;
375    int interfacesCount = readUnsignedShort(currentOffset);
376    String[] interfaces = new String[interfacesCount];
377    if (interfacesCount > 0) {
378      char[] charBuffer = new char[maxStringLength];
379      for (int i = 0; i < interfacesCount; ++i) {
380        currentOffset += 2;
381        interfaces[i] = readClass(currentOffset, charBuffer);
382      }
383    }
384    return interfaces;
385  }
386
387  // -----------------------------------------------------------------------------------------------
388  // Public methods
389  // -----------------------------------------------------------------------------------------------
390
391  /**
392   * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
393   * {@link ClassReader}.
394   *
395   * @param classVisitor the visitor that must visit this class.
396   * @param parsingOptions the options to use to parse this class. One or more of {@link
397   *     #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}.
398   */
399  public void accept(final ClassVisitor classVisitor, final int parsingOptions) {
400    accept(classVisitor, new Attribute[0], parsingOptions);
401  }
402
403  /**
404   * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
405   * {@link ClassReader}.
406   *
407   * @param classVisitor the visitor that must visit this class.
408   * @param attributePrototypes prototypes of the attributes that must be parsed during the visit of
409   *     the class. Any attribute whose type is not equal to the type of one the prototypes will not
410   *     be parsed: its byte array value will be passed unchanged to the ClassWriter. <i>This may
411   *     corrupt it if this value contains references to the constant pool, or has syntactic or
412   *     semantic links with a class element that has been transformed by a class adapter between
413   *     the reader and the writer</i>.
414   * @param parsingOptions the options to use to parse this class. One or more of {@link
415   *     #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}.
416   */
417  public void accept(
418      final ClassVisitor classVisitor,
419      final Attribute[] attributePrototypes,
420      final int parsingOptions) {
421    Context context = new Context();
422    context.attributePrototypes = attributePrototypes;
423    context.parsingOptions = parsingOptions;
424    context.charBuffer = new char[maxStringLength];
425
426    // Read the access_flags, this_class, super_class, interface_count and interfaces fields.
427    char[] charBuffer = context.charBuffer;
428    int currentOffset = header;
429    int accessFlags = readUnsignedShort(currentOffset);
430    String thisClass = readClass(currentOffset + 2, charBuffer);
431    String superClass = readClass(currentOffset + 4, charBuffer);
432    String[] interfaces = new String[readUnsignedShort(currentOffset + 6)];
433    currentOffset += 8;
434    for (int i = 0; i < interfaces.length; ++i) {
435      interfaces[i] = readClass(currentOffset, charBuffer);
436      currentOffset += 2;
437    }
438
439    // Read the class attributes (the variables are ordered as in Section 4.7 of the JVMS).
440    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
441    // - The offset of the InnerClasses attribute, or 0.
442    int innerClassesOffset = 0;
443    // - The offset of the EnclosingMethod attribute, or 0.
444    int enclosingMethodOffset = 0;
445    // - The string corresponding to the Signature attribute, or null.
446    String signature = null;
447    // - The string corresponding to the SourceFile attribute, or null.
448    String sourceFile = null;
449    // - The string corresponding to the SourceDebugExtension attribute, or null.
450    String sourceDebugExtension = null;
451    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
452    int runtimeVisibleAnnotationsOffset = 0;
453    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
454    int runtimeInvisibleAnnotationsOffset = 0;
455    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
456    int runtimeVisibleTypeAnnotationsOffset = 0;
457    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
458    int runtimeInvisibleTypeAnnotationsOffset = 0;
459    // - The offset of the Module attribute, or 0.
460    int moduleOffset = 0;
461    // - The offset of the ModulePackages attribute, or 0.
462    int modulePackagesOffset = 0;
463    // - The string corresponding to the ModuleMainClass attribute, or null.
464    String moduleMainClass = null;
465    // - The string corresponding to the NestHost attribute, or null.
466    String nestHostClass = null;
467    // - The offset of the NestMembers attribute, or 0.
468    int nestMembersOffset = 0;
469    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
470    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
471    Attribute attributes = null;
472
473    int currentAttributeOffset = getFirstAttributeOffset();
474    for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) {
475      // Read the attribute_info's attribute_name and attribute_length fields.
476      String attributeName = readUTF8(currentAttributeOffset, charBuffer);
477      int attributeLength = readInt(currentAttributeOffset + 2);
478      currentAttributeOffset += 6;
479      // The tests are sorted in decreasing frequency order (based on frequencies observed on
480      // typical classes).
481      if (Constants.SOURCE_FILE.equals(attributeName)) {
482        sourceFile = readUTF8(currentAttributeOffset, charBuffer);
483      } else if (Constants.INNER_CLASSES.equals(attributeName)) {
484        innerClassesOffset = currentAttributeOffset;
485      } else if (Constants.ENCLOSING_METHOD.equals(attributeName)) {
486        enclosingMethodOffset = currentAttributeOffset;
487      } else if (Constants.NEST_HOST.equals(attributeName)) {
488        nestHostClass = readClass(currentAttributeOffset, charBuffer);
489      } else if (Constants.NEST_MEMBERS.equals(attributeName)) {
490        nestMembersOffset = currentAttributeOffset;
491      } else if (Constants.SIGNATURE.equals(attributeName)) {
492        signature = readUTF8(currentAttributeOffset, charBuffer);
493      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
494        runtimeVisibleAnnotationsOffset = currentAttributeOffset;
495      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
496        runtimeVisibleTypeAnnotationsOffset = currentAttributeOffset;
497      } else if (Constants.DEPRECATED.equals(attributeName)) {
498        accessFlags |= Opcodes.ACC_DEPRECATED;
499      } else if (Constants.SYNTHETIC.equals(attributeName)) {
500        accessFlags |= Opcodes.ACC_SYNTHETIC;
501      } else if (Constants.SOURCE_DEBUG_EXTENSION.equals(attributeName)) {
502        sourceDebugExtension =
503            readUtf(currentAttributeOffset, attributeLength, new char[attributeLength]);
504      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
505        runtimeInvisibleAnnotationsOffset = currentAttributeOffset;
506      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
507        runtimeInvisibleTypeAnnotationsOffset = currentAttributeOffset;
508      } else if (Constants.MODULE.equals(attributeName)) {
509        moduleOffset = currentAttributeOffset;
510      } else if (Constants.MODULE_MAIN_CLASS.equals(attributeName)) {
511        moduleMainClass = readClass(currentAttributeOffset, charBuffer);
512      } else if (Constants.MODULE_PACKAGES.equals(attributeName)) {
513        modulePackagesOffset = currentAttributeOffset;
514      } else if (!Constants.BOOTSTRAP_METHODS.equals(attributeName)) {
515        // The BootstrapMethods attribute is read in the constructor.
516        Attribute attribute =
517            readAttribute(
518                attributePrototypes,
519                attributeName,
520                currentAttributeOffset,
521                attributeLength,
522                charBuffer,
523                -1,
524                null);
525        attribute.nextAttribute = attributes;
526        attributes = attribute;
527      }
528      currentAttributeOffset += attributeLength;
529    }
530
531    // Visit the class declaration. The minor_version and major_version fields start 6 bytes before
532    // the first constant pool entry, which itself starts at cpInfoOffsets[1] - 1 (by definition).
533    classVisitor.visit(
534        readInt(cpInfoOffsets[1] - 7), accessFlags, thisClass, signature, superClass, interfaces);
535
536    // Visit the SourceFile and SourceDebugExtenstion attributes.
537    if ((parsingOptions & SKIP_DEBUG) == 0
538        && (sourceFile != null || sourceDebugExtension != null)) {
539      classVisitor.visitSource(sourceFile, sourceDebugExtension);
540    }
541
542    // Visit the Module, ModulePackages and ModuleMainClass attributes.
543    if (moduleOffset != 0) {
544      readModuleAttributes(
545          classVisitor, context, moduleOffset, modulePackagesOffset, moduleMainClass);
546    }
547
548    // Visit the NestHost attribute.
549    if (nestHostClass != null) {
550      classVisitor.visitNestHost(nestHostClass);
551    }
552
553    // Visit the EnclosingMethod attribute.
554    if (enclosingMethodOffset != 0) {
555      String className = readClass(enclosingMethodOffset, charBuffer);
556      int methodIndex = readUnsignedShort(enclosingMethodOffset + 2);
557      String name = methodIndex == 0 ? null : readUTF8(cpInfoOffsets[methodIndex], charBuffer);
558      String type = methodIndex == 0 ? null : readUTF8(cpInfoOffsets[methodIndex] + 2, charBuffer);
559      classVisitor.visitOuterClass(className, name, type);
560    }
561
562    // Visit the RuntimeVisibleAnnotations attribute.
563    if (runtimeVisibleAnnotationsOffset != 0) {
564      int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
565      int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
566      while (numAnnotations-- > 0) {
567        // Parse the type_index field.
568        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
569        currentAnnotationOffset += 2;
570        // Parse num_element_value_pairs and element_value_pairs and visit these values.
571        currentAnnotationOffset =
572            readElementValues(
573                classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
574                currentAnnotationOffset,
575                /* named = */ true,
576                charBuffer);
577      }
578    }
579
580    // Visit the RuntimeInvisibleAnnotations attribute.
581    if (runtimeInvisibleAnnotationsOffset != 0) {
582      int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
583      int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
584      while (numAnnotations-- > 0) {
585        // Parse the type_index field.
586        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
587        currentAnnotationOffset += 2;
588        // Parse num_element_value_pairs and element_value_pairs and visit these values.
589        currentAnnotationOffset =
590            readElementValues(
591                classVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
592                currentAnnotationOffset,
593                /* named = */ true,
594                charBuffer);
595      }
596    }
597
598    // Visit the RuntimeVisibleTypeAnnotations attribute.
599    if (runtimeVisibleTypeAnnotationsOffset != 0) {
600      int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
601      int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
602      while (numAnnotations-- > 0) {
603        // Parse the target_type, target_info and target_path fields.
604        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
605        // Parse the type_index field.
606        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
607        currentAnnotationOffset += 2;
608        // Parse num_element_value_pairs and element_value_pairs and visit these values.
609        currentAnnotationOffset =
610            readElementValues(
611                classVisitor.visitTypeAnnotation(
612                    context.currentTypeAnnotationTarget,
613                    context.currentTypeAnnotationTargetPath,
614                    annotationDescriptor,
615                    /* visible = */ true),
616                currentAnnotationOffset,
617                /* named = */ true,
618                charBuffer);
619      }
620    }
621
622    // Visit the RuntimeInvisibleTypeAnnotations attribute.
623    if (runtimeInvisibleTypeAnnotationsOffset != 0) {
624      int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
625      int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
626      while (numAnnotations-- > 0) {
627        // Parse the target_type, target_info and target_path fields.
628        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
629        // Parse the type_index field.
630        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
631        currentAnnotationOffset += 2;
632        // Parse num_element_value_pairs and element_value_pairs and visit these values.
633        currentAnnotationOffset =
634            readElementValues(
635                classVisitor.visitTypeAnnotation(
636                    context.currentTypeAnnotationTarget,
637                    context.currentTypeAnnotationTargetPath,
638                    annotationDescriptor,
639                    /* visible = */ false),
640                currentAnnotationOffset,
641                /* named = */ true,
642                charBuffer);
643      }
644    }
645
646    // Visit the non standard attributes.
647    while (attributes != null) {
648      // Copy and reset the nextAttribute field so that it can also be used in ClassWriter.
649      Attribute nextAttribute = attributes.nextAttribute;
650      attributes.nextAttribute = null;
651      classVisitor.visitAttribute(attributes);
652      attributes = nextAttribute;
653    }
654
655    // Visit the NestedMembers attribute.
656    if (nestMembersOffset != 0) {
657      int numberOfNestMembers = readUnsignedShort(nestMembersOffset);
658      int currentNestMemberOffset = nestMembersOffset + 2;
659      while (numberOfNestMembers-- > 0) {
660        classVisitor.visitNestMember(readClass(currentNestMemberOffset, charBuffer));
661        currentNestMemberOffset += 2;
662      }
663    }
664
665    // Visit the InnerClasses attribute.
666    if (innerClassesOffset != 0) {
667      int numberOfClasses = readUnsignedShort(innerClassesOffset);
668      int currentClassesOffset = innerClassesOffset + 2;
669      while (numberOfClasses-- > 0) {
670        classVisitor.visitInnerClass(
671            readClass(currentClassesOffset, charBuffer),
672            readClass(currentClassesOffset + 2, charBuffer),
673            readUTF8(currentClassesOffset + 4, charBuffer),
674            readUnsignedShort(currentClassesOffset + 6));
675        currentClassesOffset += 8;
676      }
677    }
678
679    // Visit the fields and methods.
680    int fieldsCount = readUnsignedShort(currentOffset);
681    currentOffset += 2;
682    while (fieldsCount-- > 0) {
683      currentOffset = readField(classVisitor, context, currentOffset);
684    }
685    int methodsCount = readUnsignedShort(currentOffset);
686    currentOffset += 2;
687    while (methodsCount-- > 0) {
688      currentOffset = readMethod(classVisitor, context, currentOffset);
689    }
690
691    // Visit the end of the class.
692    classVisitor.visitEnd();
693  }
694
695  // ----------------------------------------------------------------------------------------------
696  // Methods to parse modules, fields and methods
697  // ----------------------------------------------------------------------------------------------
698
699  /**
700   * Reads the Module, ModulePackages and ModuleMainClass attributes and visit them.
701   *
702   * @param classVisitor the current class visitor
703   * @param context information about the class being parsed.
704   * @param moduleOffset the offset of the Module attribute (excluding the attribute_info's
705   *     attribute_name_index and attribute_length fields).
706   * @param modulePackagesOffset the offset of the ModulePackages attribute (excluding the
707   *     attribute_info's attribute_name_index and attribute_length fields), or 0.
708   * @param moduleMainClass the string corresponding to the ModuleMainClass attribute, or null.
709   */
710  private void readModuleAttributes(
711      final ClassVisitor classVisitor,
712      final Context context,
713      final int moduleOffset,
714      final int modulePackagesOffset,
715      final String moduleMainClass) {
716    char[] buffer = context.charBuffer;
717
718    // Read the module_name_index, module_flags and module_version_index fields and visit them.
719    int currentOffset = moduleOffset;
720    String moduleName = readModule(currentOffset, buffer);
721    int moduleFlags = readUnsignedShort(currentOffset + 2);
722    String moduleVersion = readUTF8(currentOffset + 4, buffer);
723    currentOffset += 6;
724    ModuleVisitor moduleVisitor = classVisitor.visitModule(moduleName, moduleFlags, moduleVersion);
725    if (moduleVisitor == null) {
726      return;
727    }
728
729    // Visit the ModuleMainClass attribute.
730    if (moduleMainClass != null) {
731      moduleVisitor.visitMainClass(moduleMainClass);
732    }
733
734    // Visit the ModulePackages attribute.
735    if (modulePackagesOffset != 0) {
736      int packageCount = readUnsignedShort(modulePackagesOffset);
737      int currentPackageOffset = modulePackagesOffset + 2;
738      while (packageCount-- > 0) {
739        moduleVisitor.visitPackage(readPackage(currentPackageOffset, buffer));
740        currentPackageOffset += 2;
741      }
742    }
743
744    // Read the 'requires_count' and 'requires' fields.
745    int requiresCount = readUnsignedShort(currentOffset);
746    currentOffset += 2;
747    while (requiresCount-- > 0) {
748      // Read the requires_index, requires_flags and requires_version fields and visit them.
749      String requires = readModule(currentOffset, buffer);
750      int requiresFlags = readUnsignedShort(currentOffset + 2);
751      String requiresVersion = readUTF8(currentOffset + 4, buffer);
752      currentOffset += 6;
753      moduleVisitor.visitRequire(requires, requiresFlags, requiresVersion);
754    }
755
756    // Read the 'exports_count' and 'exports' fields.
757    int exportsCount = readUnsignedShort(currentOffset);
758    currentOffset += 2;
759    while (exportsCount-- > 0) {
760      // Read the exports_index, exports_flags, exports_to_count and exports_to_index fields
761      // and visit them.
762      String exports = readPackage(currentOffset, buffer);
763      int exportsFlags = readUnsignedShort(currentOffset + 2);
764      int exportsToCount = readUnsignedShort(currentOffset + 4);
765      currentOffset += 6;
766      String[] exportsTo = null;
767      if (exportsToCount != 0) {
768        exportsTo = new String[exportsToCount];
769        for (int i = 0; i < exportsToCount; ++i) {
770          exportsTo[i] = readModule(currentOffset, buffer);
771          currentOffset += 2;
772        }
773      }
774      moduleVisitor.visitExport(exports, exportsFlags, exportsTo);
775    }
776
777    // Reads the 'opens_count' and 'opens' fields.
778    int opensCount = readUnsignedShort(currentOffset);
779    currentOffset += 2;
780    while (opensCount-- > 0) {
781      // Read the opens_index, opens_flags, opens_to_count and opens_to_index fields and visit them.
782      String opens = readPackage(currentOffset, buffer);
783      int opensFlags = readUnsignedShort(currentOffset + 2);
784      int opensToCount = readUnsignedShort(currentOffset + 4);
785      currentOffset += 6;
786      String[] opensTo = null;
787      if (opensToCount != 0) {
788        opensTo = new String[opensToCount];
789        for (int i = 0; i < opensToCount; ++i) {
790          opensTo[i] = readModule(currentOffset, buffer);
791          currentOffset += 2;
792        }
793      }
794      moduleVisitor.visitOpen(opens, opensFlags, opensTo);
795    }
796
797    // Read the 'uses_count' and 'uses' fields.
798    int usesCount = readUnsignedShort(currentOffset);
799    currentOffset += 2;
800    while (usesCount-- > 0) {
801      moduleVisitor.visitUse(readClass(currentOffset, buffer));
802      currentOffset += 2;
803    }
804
805    // Read the  'provides_count' and 'provides' fields.
806    int providesCount = readUnsignedShort(currentOffset);
807    currentOffset += 2;
808    while (providesCount-- > 0) {
809      // Read the provides_index, provides_with_count and provides_with_index fields and visit them.
810      String provides = readClass(currentOffset, buffer);
811      int providesWithCount = readUnsignedShort(currentOffset + 2);
812      currentOffset += 4;
813      String[] providesWith = new String[providesWithCount];
814      for (int i = 0; i < providesWithCount; ++i) {
815        providesWith[i] = readClass(currentOffset, buffer);
816        currentOffset += 2;
817      }
818      moduleVisitor.visitProvide(provides, providesWith);
819    }
820
821    // Visit the end of the module attributes.
822    moduleVisitor.visitEnd();
823  }
824
825  /**
826   * Reads a JVMS field_info structure and makes the given visitor visit it.
827   *
828   * @param classVisitor the visitor that must visit the field.
829   * @param context information about the class being parsed.
830   * @param fieldInfoOffset the start offset of the field_info structure.
831   * @return the offset of the first byte following the field_info structure.
832   */
833  private int readField(
834    final ClassVisitor classVisitor, final Context context, final int fieldInfoOffset) {
835    char[] charBuffer = context.charBuffer;
836
837    // Read the access_flags, name_index and descriptor_index fields.
838    int currentOffset = fieldInfoOffset;
839    int accessFlags = readUnsignedShort(currentOffset);
840    String name = readUTF8(currentOffset + 2, charBuffer);
841    String descriptor = readUTF8(currentOffset + 4, charBuffer);
842    currentOffset += 6;
843
844    // Read the field attributes (the variables are ordered as in Section 4.7 of the JVMS).
845    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
846    // - The value corresponding to the ConstantValue attribute, or null.
847    Object constantValue = null;
848    // - The string corresponding to the Signature attribute, or null.
849    String signature = null;
850    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
851    int runtimeVisibleAnnotationsOffset = 0;
852    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
853    int runtimeInvisibleAnnotationsOffset = 0;
854    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
855    int runtimeVisibleTypeAnnotationsOffset = 0;
856    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
857    int runtimeInvisibleTypeAnnotationsOffset = 0;
858    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
859    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
860    Attribute attributes = null;
861
862    int attributesCount = readUnsignedShort(currentOffset);
863    currentOffset += 2;
864    while (attributesCount-- > 0) {
865      // Read the attribute_info's attribute_name and attribute_length fields.
866      String attributeName = readUTF8(currentOffset, charBuffer);
867      int attributeLength = readInt(currentOffset + 2);
868      currentOffset += 6;
869      // The tests are sorted in decreasing frequency order (based on frequencies observed on
870      // typical classes).
871      if (Constants.CONSTANT_VALUE.equals(attributeName)) {
872        int constantvalueIndex = readUnsignedShort(currentOffset);
873        constantValue = constantvalueIndex == 0 ? null : readConst(constantvalueIndex, charBuffer);
874      } else if (Constants.SIGNATURE.equals(attributeName)) {
875        signature = readUTF8(currentOffset, charBuffer);
876      } else if (Constants.DEPRECATED.equals(attributeName)) {
877        accessFlags |= Opcodes.ACC_DEPRECATED;
878      } else if (Constants.SYNTHETIC.equals(attributeName)) {
879        accessFlags |= Opcodes.ACC_SYNTHETIC;
880      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
881        runtimeVisibleAnnotationsOffset = currentOffset;
882      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
883        runtimeVisibleTypeAnnotationsOffset = currentOffset;
884      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
885        runtimeInvisibleAnnotationsOffset = currentOffset;
886      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
887        runtimeInvisibleTypeAnnotationsOffset = currentOffset;
888      } else {
889        Attribute attribute =
890            readAttribute(
891                context.attributePrototypes,
892                attributeName,
893                currentOffset,
894                attributeLength,
895                charBuffer,
896                -1,
897                null);
898        attribute.nextAttribute = attributes;
899        attributes = attribute;
900      }
901      currentOffset += attributeLength;
902    }
903
904    // Visit the field declaration.
905    FieldVisitor fieldVisitor =
906        classVisitor.visitField(accessFlags, name, descriptor, signature, constantValue);
907    if (fieldVisitor == null) {
908      return currentOffset;
909    }
910
911    // Visit the RuntimeVisibleAnnotations attribute.
912    if (runtimeVisibleAnnotationsOffset != 0) {
913      int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
914      int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
915      while (numAnnotations-- > 0) {
916        // Parse the type_index field.
917        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
918        currentAnnotationOffset += 2;
919        // Parse num_element_value_pairs and element_value_pairs and visit these values.
920        currentAnnotationOffset =
921            readElementValues(
922                fieldVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
923                currentAnnotationOffset,
924                /* named = */ true,
925                charBuffer);
926      }
927    }
928
929    // Visit the RuntimeInvisibleAnnotations attribute.
930    if (runtimeInvisibleAnnotationsOffset != 0) {
931      int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
932      int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
933      while (numAnnotations-- > 0) {
934        // Parse the type_index field.
935        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
936        currentAnnotationOffset += 2;
937        // Parse num_element_value_pairs and element_value_pairs and visit these values.
938        currentAnnotationOffset =
939            readElementValues(
940                fieldVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
941                currentAnnotationOffset,
942                /* named = */ true,
943                charBuffer);
944      }
945    }
946
947    // Visit the RuntimeVisibleTypeAnnotations attribute.
948    if (runtimeVisibleTypeAnnotationsOffset != 0) {
949      int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
950      int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
951      while (numAnnotations-- > 0) {
952        // Parse the target_type, target_info and target_path fields.
953        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
954        // Parse the type_index field.
955        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
956        currentAnnotationOffset += 2;
957        // Parse num_element_value_pairs and element_value_pairs and visit these values.
958        currentAnnotationOffset =
959            readElementValues(
960                fieldVisitor.visitTypeAnnotation(
961                    context.currentTypeAnnotationTarget,
962                    context.currentTypeAnnotationTargetPath,
963                    annotationDescriptor,
964                    /* visible = */ true),
965                currentAnnotationOffset,
966                /* named = */ true,
967                charBuffer);
968      }
969    }
970
971    // Visit the RuntimeInvisibleTypeAnnotations attribute.
972    if (runtimeInvisibleTypeAnnotationsOffset != 0) {
973      int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
974      int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
975      while (numAnnotations-- > 0) {
976        // Parse the target_type, target_info and target_path fields.
977        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
978        // Parse the type_index field.
979        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
980        currentAnnotationOffset += 2;
981        // Parse num_element_value_pairs and element_value_pairs and visit these values.
982        currentAnnotationOffset =
983            readElementValues(
984                fieldVisitor.visitTypeAnnotation(
985                    context.currentTypeAnnotationTarget,
986                    context.currentTypeAnnotationTargetPath,
987                    annotationDescriptor,
988                    /* visible = */ false),
989                currentAnnotationOffset,
990                /* named = */ true,
991                charBuffer);
992      }
993    }
994
995    // Visit the non standard attributes.
996    while (attributes != null) {
997      // Copy and reset the nextAttribute field so that it can also be used in FieldWriter.
998      Attribute nextAttribute = attributes.nextAttribute;
999      attributes.nextAttribute = null;
1000      fieldVisitor.visitAttribute(attributes);
1001      attributes = nextAttribute;
1002    }
1003
1004    // Visit the end of the field.
1005    fieldVisitor.visitEnd();
1006    return currentOffset;
1007  }
1008
1009  /**
1010   * Reads a JVMS method_info structure and makes the given visitor visit it.
1011   *
1012   * @param classVisitor the visitor that must visit the method.
1013   * @param context information about the class being parsed.
1014   * @param methodInfoOffset the start offset of the method_info structure.
1015   * @return the offset of the first byte following the method_info structure.
1016   */
1017  private int readMethod(
1018    final ClassVisitor classVisitor, final Context context, final int methodInfoOffset) {
1019    char[] charBuffer = context.charBuffer;
1020
1021    // Read the access_flags, name_index and descriptor_index fields.
1022    int currentOffset = methodInfoOffset;
1023    context.currentMethodAccessFlags = readUnsignedShort(currentOffset);
1024    context.currentMethodName = readUTF8(currentOffset + 2, charBuffer);
1025    context.currentMethodDescriptor = readUTF8(currentOffset + 4, charBuffer);
1026    currentOffset += 6;
1027
1028    // Read the method attributes (the variables are ordered as in Section 4.7 of the JVMS).
1029    // Attribute offsets exclude the attribute_name_index and attribute_length fields.
1030    // - The offset of the Code attribute, or 0.
1031    int codeOffset = 0;
1032    // - The offset of the Exceptions attribute, or 0.
1033    int exceptionsOffset = 0;
1034    // - The strings corresponding to the Exceptions attribute, or null.
1035    String[] exceptions = null;
1036    // - Whether the method has a Synthetic attribute.
1037    boolean synthetic = false;
1038    // - The constant pool index contained in the Signature attribute, or 0.
1039    int signatureIndex = 0;
1040    // - The offset of the RuntimeVisibleAnnotations attribute, or 0.
1041    int runtimeVisibleAnnotationsOffset = 0;
1042    // - The offset of the RuntimeInvisibleAnnotations attribute, or 0.
1043    int runtimeInvisibleAnnotationsOffset = 0;
1044    // - The offset of the RuntimeVisibleParameterAnnotations attribute, or 0.
1045    int runtimeVisibleParameterAnnotationsOffset = 0;
1046    // - The offset of the RuntimeInvisibleParameterAnnotations attribute, or 0.
1047    int runtimeInvisibleParameterAnnotationsOffset = 0;
1048    // - The offset of the RuntimeVisibleTypeAnnotations attribute, or 0.
1049    int runtimeVisibleTypeAnnotationsOffset = 0;
1050    // - The offset of the RuntimeInvisibleTypeAnnotations attribute, or 0.
1051    int runtimeInvisibleTypeAnnotationsOffset = 0;
1052    // - The offset of the AnnotationDefault attribute, or 0.
1053    int annotationDefaultOffset = 0;
1054    // - The offset of the MethodParameters attribute, or 0.
1055    int methodParametersOffset = 0;
1056    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
1057    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
1058    Attribute attributes = null;
1059
1060    int attributesCount = readUnsignedShort(currentOffset);
1061    currentOffset += 2;
1062    while (attributesCount-- > 0) {
1063      // Read the attribute_info's attribute_name and attribute_length fields.
1064      String attributeName = readUTF8(currentOffset, charBuffer);
1065      int attributeLength = readInt(currentOffset + 2);
1066      currentOffset += 6;
1067      // The tests are sorted in decreasing frequency order (based on frequencies observed on
1068      // typical classes).
1069      if (Constants.CODE.equals(attributeName)) {
1070        if ((context.parsingOptions & SKIP_CODE) == 0) {
1071          codeOffset = currentOffset;
1072        }
1073      } else if (Constants.EXCEPTIONS.equals(attributeName)) {
1074        exceptionsOffset = currentOffset;
1075        exceptions = new String[readUnsignedShort(exceptionsOffset)];
1076        int currentExceptionOffset = exceptionsOffset + 2;
1077        for (int i = 0; i < exceptions.length; ++i) {
1078          exceptions[i] = readClass(currentExceptionOffset, charBuffer);
1079          currentExceptionOffset += 2;
1080        }
1081      } else if (Constants.SIGNATURE.equals(attributeName)) {
1082        signatureIndex = readUnsignedShort(currentOffset);
1083      } else if (Constants.DEPRECATED.equals(attributeName)) {
1084        context.currentMethodAccessFlags |= Opcodes.ACC_DEPRECATED;
1085      } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) {
1086        runtimeVisibleAnnotationsOffset = currentOffset;
1087      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1088        runtimeVisibleTypeAnnotationsOffset = currentOffset;
1089      } else if (Constants.ANNOTATION_DEFAULT.equals(attributeName)) {
1090        annotationDefaultOffset = currentOffset;
1091      } else if (Constants.SYNTHETIC.equals(attributeName)) {
1092        synthetic = true;
1093        context.currentMethodAccessFlags |= Opcodes.ACC_SYNTHETIC;
1094      } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) {
1095        runtimeInvisibleAnnotationsOffset = currentOffset;
1096      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1097        runtimeInvisibleTypeAnnotationsOffset = currentOffset;
1098      } else if (Constants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS.equals(attributeName)) {
1099        runtimeVisibleParameterAnnotationsOffset = currentOffset;
1100      } else if (Constants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS.equals(attributeName)) {
1101        runtimeInvisibleParameterAnnotationsOffset = currentOffset;
1102      } else if (Constants.METHOD_PARAMETERS.equals(attributeName)) {
1103        methodParametersOffset = currentOffset;
1104      } else {
1105        Attribute attribute =
1106            readAttribute(
1107                context.attributePrototypes,
1108                attributeName,
1109                currentOffset,
1110                attributeLength,
1111                charBuffer,
1112                -1,
1113                null);
1114        attribute.nextAttribute = attributes;
1115        attributes = attribute;
1116      }
1117      currentOffset += attributeLength;
1118    }
1119
1120    // Visit the method declaration.
1121    MethodVisitor methodVisitor =
1122        classVisitor.visitMethod(
1123            context.currentMethodAccessFlags,
1124            context.currentMethodName,
1125            context.currentMethodDescriptor,
1126            signatureIndex == 0 ? null : readUtf(signatureIndex, charBuffer),
1127            exceptions);
1128    if (methodVisitor == null) {
1129      return currentOffset;
1130    }
1131
1132    // If the returned MethodVisitor is in fact a MethodWriter, it means there is no method
1133    // adapter between the reader and the writer. In this case, it might be possible to copy
1134    // the method attributes directly into the writer. If so, return early without visiting
1135    // the content of these attributes.
1136    if (methodVisitor instanceof MethodWriter) {
1137      MethodWriter methodWriter = (MethodWriter) methodVisitor;
1138      if (methodWriter.canCopyMethodAttributes(
1139          this,
1140          synthetic,
1141          (context.currentMethodAccessFlags & Opcodes.ACC_DEPRECATED) != 0,
1142          readUnsignedShort(methodInfoOffset + 4),
1143          signatureIndex,
1144          exceptionsOffset)) {
1145        methodWriter.setMethodAttributesSource(methodInfoOffset, currentOffset - methodInfoOffset);
1146        return currentOffset;
1147      }
1148    }
1149
1150    // Visit the MethodParameters attribute.
1151    if (methodParametersOffset != 0) {
1152      int parametersCount = readByte(methodParametersOffset);
1153      int currentParameterOffset = methodParametersOffset + 1;
1154      while (parametersCount-- > 0) {
1155        // Read the name_index and access_flags fields and visit them.
1156        methodVisitor.visitParameter(
1157            readUTF8(currentParameterOffset, charBuffer),
1158            readUnsignedShort(currentParameterOffset + 2));
1159        currentParameterOffset += 4;
1160      }
1161    }
1162
1163    // Visit the AnnotationDefault attribute.
1164    if (annotationDefaultOffset != 0) {
1165      AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotationDefault();
1166      readElementValue(annotationVisitor, annotationDefaultOffset, null, charBuffer);
1167      if (annotationVisitor != null) {
1168        annotationVisitor.visitEnd();
1169      }
1170    }
1171
1172    // Visit the RuntimeVisibleAnnotations attribute.
1173    if (runtimeVisibleAnnotationsOffset != 0) {
1174      int numAnnotations = readUnsignedShort(runtimeVisibleAnnotationsOffset);
1175      int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2;
1176      while (numAnnotations-- > 0) {
1177        // Parse the type_index field.
1178        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1179        currentAnnotationOffset += 2;
1180        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1181        currentAnnotationOffset =
1182            readElementValues(
1183                methodVisitor.visitAnnotation(annotationDescriptor, /* visible = */ true),
1184                currentAnnotationOffset,
1185                /* named = */ true,
1186                charBuffer);
1187      }
1188    }
1189
1190    // Visit the RuntimeInvisibleAnnotations attribute.
1191    if (runtimeInvisibleAnnotationsOffset != 0) {
1192      int numAnnotations = readUnsignedShort(runtimeInvisibleAnnotationsOffset);
1193      int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2;
1194      while (numAnnotations-- > 0) {
1195        // Parse the type_index field.
1196        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1197        currentAnnotationOffset += 2;
1198        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1199        currentAnnotationOffset =
1200            readElementValues(
1201                methodVisitor.visitAnnotation(annotationDescriptor, /* visible = */ false),
1202                currentAnnotationOffset,
1203                /* named = */ true,
1204                charBuffer);
1205      }
1206    }
1207
1208    // Visit the RuntimeVisibleTypeAnnotations attribute.
1209    if (runtimeVisibleTypeAnnotationsOffset != 0) {
1210      int numAnnotations = readUnsignedShort(runtimeVisibleTypeAnnotationsOffset);
1211      int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2;
1212      while (numAnnotations-- > 0) {
1213        // Parse the target_type, target_info and target_path fields.
1214        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
1215        // Parse the type_index field.
1216        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1217        currentAnnotationOffset += 2;
1218        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1219        currentAnnotationOffset =
1220            readElementValues(
1221                methodVisitor.visitTypeAnnotation(
1222                    context.currentTypeAnnotationTarget,
1223                    context.currentTypeAnnotationTargetPath,
1224                    annotationDescriptor,
1225                    /* visible = */ true),
1226                currentAnnotationOffset,
1227                /* named = */ true,
1228                charBuffer);
1229      }
1230    }
1231
1232    // Visit the RuntimeInvisibleTypeAnnotations attribute.
1233    if (runtimeInvisibleTypeAnnotationsOffset != 0) {
1234      int numAnnotations = readUnsignedShort(runtimeInvisibleTypeAnnotationsOffset);
1235      int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2;
1236      while (numAnnotations-- > 0) {
1237        // Parse the target_type, target_info and target_path fields.
1238        currentAnnotationOffset = readTypeAnnotationTarget(context, currentAnnotationOffset);
1239        // Parse the type_index field.
1240        String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
1241        currentAnnotationOffset += 2;
1242        // Parse num_element_value_pairs and element_value_pairs and visit these values.
1243        currentAnnotationOffset =
1244            readElementValues(
1245                methodVisitor.visitTypeAnnotation(
1246                    context.currentTypeAnnotationTarget,
1247                    context.currentTypeAnnotationTargetPath,
1248                    annotationDescriptor,
1249                    /* visible = */ false),
1250                currentAnnotationOffset,
1251                /* named = */ true,
1252                charBuffer);
1253      }
1254    }
1255
1256    // Visit the RuntimeVisibleParameterAnnotations attribute.
1257    if (runtimeVisibleParameterAnnotationsOffset != 0) {
1258      readParameterAnnotations(
1259          methodVisitor, context, runtimeVisibleParameterAnnotationsOffset, /* visible = */ true);
1260    }
1261
1262    // Visit the RuntimeInvisibleParameterAnnotations attribute.
1263    if (runtimeInvisibleParameterAnnotationsOffset != 0) {
1264      readParameterAnnotations(
1265          methodVisitor,
1266          context,
1267          runtimeInvisibleParameterAnnotationsOffset,
1268          /* visible = */ false);
1269    }
1270
1271    // Visit the non standard attributes.
1272    while (attributes != null) {
1273      // Copy and reset the nextAttribute field so that it can also be used in MethodWriter.
1274      Attribute nextAttribute = attributes.nextAttribute;
1275      attributes.nextAttribute = null;
1276      methodVisitor.visitAttribute(attributes);
1277      attributes = nextAttribute;
1278    }
1279
1280    // Visit the Code attribute.
1281    if (codeOffset != 0) {
1282      methodVisitor.visitCode();
1283      readCode(methodVisitor, context, codeOffset);
1284    }
1285
1286    // Visit the end of the method.
1287    methodVisitor.visitEnd();
1288    return currentOffset;
1289  }
1290
1291  // ----------------------------------------------------------------------------------------------
1292  // Methods to parse a Code attribute
1293  // ----------------------------------------------------------------------------------------------
1294
1295  /**
1296   * Reads a JVMS 'Code' attribute and makes the given visitor visit it.
1297   *
1298   * @param methodVisitor the visitor that must visit the Code attribute.
1299   * @param context information about the class being parsed.
1300   * @param codeOffset the start offset in {@link #classFileBuffer} of the Code attribute, excluding
1301   *     its attribute_name_index and attribute_length fields.
1302   */
1303  private void readCode(
1304    final MethodVisitor methodVisitor, final Context context, final int codeOffset) {
1305    int currentOffset = codeOffset;
1306
1307    // Read the max_stack, max_locals and code_length fields.
1308    final byte[] classBuffer = classFileBuffer;
1309    final char[] charBuffer = context.charBuffer;
1310    final int maxStack = readUnsignedShort(currentOffset);
1311    final int maxLocals = readUnsignedShort(currentOffset + 2);
1312    final int codeLength = readInt(currentOffset + 4);
1313    currentOffset += 8;
1314
1315    // Read the bytecode 'code' array to create a label for each referenced instruction.
1316    final int bytecodeStartOffset = currentOffset;
1317    final int bytecodeEndOffset = currentOffset + codeLength;
1318    final Label[] labels = context.currentMethodLabels = new Label[codeLength + 1];
1319    while (currentOffset < bytecodeEndOffset) {
1320      final int bytecodeOffset = currentOffset - bytecodeStartOffset;
1321      final int opcode = classBuffer[currentOffset] & 0xFF;
1322      switch (opcode) {
1323        case Constants.NOP:
1324        case Constants.ACONST_NULL:
1325        case Constants.ICONST_M1:
1326        case Constants.ICONST_0:
1327        case Constants.ICONST_1:
1328        case Constants.ICONST_2:
1329        case Constants.ICONST_3:
1330        case Constants.ICONST_4:
1331        case Constants.ICONST_5:
1332        case Constants.LCONST_0:
1333        case Constants.LCONST_1:
1334        case Constants.FCONST_0:
1335        case Constants.FCONST_1:
1336        case Constants.FCONST_2:
1337        case Constants.DCONST_0:
1338        case Constants.DCONST_1:
1339        case Constants.IALOAD:
1340        case Constants.LALOAD:
1341        case Constants.FALOAD:
1342        case Constants.DALOAD:
1343        case Constants.AALOAD:
1344        case Constants.BALOAD:
1345        case Constants.CALOAD:
1346        case Constants.SALOAD:
1347        case Constants.IASTORE:
1348        case Constants.LASTORE:
1349        case Constants.FASTORE:
1350        case Constants.DASTORE:
1351        case Constants.AASTORE:
1352        case Constants.BASTORE:
1353        case Constants.CASTORE:
1354        case Constants.SASTORE:
1355        case Constants.POP:
1356        case Constants.POP2:
1357        case Constants.DUP:
1358        case Constants.DUP_X1:
1359        case Constants.DUP_X2:
1360        case Constants.DUP2:
1361        case Constants.DUP2_X1:
1362        case Constants.DUP2_X2:
1363        case Constants.SWAP:
1364        case Constants.IADD:
1365        case Constants.LADD:
1366        case Constants.FADD:
1367        case Constants.DADD:
1368        case Constants.ISUB:
1369        case Constants.LSUB:
1370        case Constants.FSUB:
1371        case Constants.DSUB:
1372        case Constants.IMUL:
1373        case Constants.LMUL:
1374        case Constants.FMUL:
1375        case Constants.DMUL:
1376        case Constants.IDIV:
1377        case Constants.LDIV:
1378        case Constants.FDIV:
1379        case Constants.DDIV:
1380        case Constants.IREM:
1381        case Constants.LREM:
1382        case Constants.FREM:
1383        case Constants.DREM:
1384        case Constants.INEG:
1385        case Constants.LNEG:
1386        case Constants.FNEG:
1387        case Constants.DNEG:
1388        case Constants.ISHL:
1389        case Constants.LSHL:
1390        case Constants.ISHR:
1391        case Constants.LSHR:
1392        case Constants.IUSHR:
1393        case Constants.LUSHR:
1394        case Constants.IAND:
1395        case Constants.LAND:
1396        case Constants.IOR:
1397        case Constants.LOR:
1398        case Constants.IXOR:
1399        case Constants.LXOR:
1400        case Constants.I2L:
1401        case Constants.I2F:
1402        case Constants.I2D:
1403        case Constants.L2I:
1404        case Constants.L2F:
1405        case Constants.L2D:
1406        case Constants.F2I:
1407        case Constants.F2L:
1408        case Constants.F2D:
1409        case Constants.D2I:
1410        case Constants.D2L:
1411        case Constants.D2F:
1412        case Constants.I2B:
1413        case Constants.I2C:
1414        case Constants.I2S:
1415        case Constants.LCMP:
1416        case Constants.FCMPL:
1417        case Constants.FCMPG:
1418        case Constants.DCMPL:
1419        case Constants.DCMPG:
1420        case Constants.IRETURN:
1421        case Constants.LRETURN:
1422        case Constants.FRETURN:
1423        case Constants.DRETURN:
1424        case Constants.ARETURN:
1425        case Constants.RETURN:
1426        case Constants.ARRAYLENGTH:
1427        case Constants.ATHROW:
1428        case Constants.MONITORENTER:
1429        case Constants.MONITOREXIT:
1430        case Constants.ILOAD_0:
1431        case Constants.ILOAD_1:
1432        case Constants.ILOAD_2:
1433        case Constants.ILOAD_3:
1434        case Constants.LLOAD_0:
1435        case Constants.LLOAD_1:
1436        case Constants.LLOAD_2:
1437        case Constants.LLOAD_3:
1438        case Constants.FLOAD_0:
1439        case Constants.FLOAD_1:
1440        case Constants.FLOAD_2:
1441        case Constants.FLOAD_3:
1442        case Constants.DLOAD_0:
1443        case Constants.DLOAD_1:
1444        case Constants.DLOAD_2:
1445        case Constants.DLOAD_3:
1446        case Constants.ALOAD_0:
1447        case Constants.ALOAD_1:
1448        case Constants.ALOAD_2:
1449        case Constants.ALOAD_3:
1450        case Constants.ISTORE_0:
1451        case Constants.ISTORE_1:
1452        case Constants.ISTORE_2:
1453        case Constants.ISTORE_3:
1454        case Constants.LSTORE_0:
1455        case Constants.LSTORE_1:
1456        case Constants.LSTORE_2:
1457        case Constants.LSTORE_3:
1458        case Constants.FSTORE_0:
1459        case Constants.FSTORE_1:
1460        case Constants.FSTORE_2:
1461        case Constants.FSTORE_3:
1462        case Constants.DSTORE_0:
1463        case Constants.DSTORE_1:
1464        case Constants.DSTORE_2:
1465        case Constants.DSTORE_3:
1466        case Constants.ASTORE_0:
1467        case Constants.ASTORE_1:
1468        case Constants.ASTORE_2:
1469        case Constants.ASTORE_3:
1470          currentOffset += 1;
1471          break;
1472        case Constants.IFEQ:
1473        case Constants.IFNE:
1474        case Constants.IFLT:
1475        case Constants.IFGE:
1476        case Constants.IFGT:
1477        case Constants.IFLE:
1478        case Constants.IF_ICMPEQ:
1479        case Constants.IF_ICMPNE:
1480        case Constants.IF_ICMPLT:
1481        case Constants.IF_ICMPGE:
1482        case Constants.IF_ICMPGT:
1483        case Constants.IF_ICMPLE:
1484        case Constants.IF_ACMPEQ:
1485        case Constants.IF_ACMPNE:
1486        case Constants.GOTO:
1487        case Constants.JSR:
1488        case Constants.IFNULL:
1489        case Constants.IFNONNULL:
1490          createLabel(bytecodeOffset + readShort(currentOffset + 1), labels);
1491          currentOffset += 3;
1492          break;
1493        case Constants.ASM_IFEQ:
1494        case Constants.ASM_IFNE:
1495        case Constants.ASM_IFLT:
1496        case Constants.ASM_IFGE:
1497        case Constants.ASM_IFGT:
1498        case Constants.ASM_IFLE:
1499        case Constants.ASM_IF_ICMPEQ:
1500        case Constants.ASM_IF_ICMPNE:
1501        case Constants.ASM_IF_ICMPLT:
1502        case Constants.ASM_IF_ICMPGE:
1503        case Constants.ASM_IF_ICMPGT:
1504        case Constants.ASM_IF_ICMPLE:
1505        case Constants.ASM_IF_ACMPEQ:
1506        case Constants.ASM_IF_ACMPNE:
1507        case Constants.ASM_GOTO:
1508        case Constants.ASM_JSR:
1509        case Constants.ASM_IFNULL:
1510        case Constants.ASM_IFNONNULL:
1511          createLabel(bytecodeOffset + readUnsignedShort(currentOffset + 1), labels);
1512          currentOffset += 3;
1513          break;
1514        case Constants.GOTO_W:
1515        case Constants.JSR_W:
1516        case Constants.ASM_GOTO_W:
1517          createLabel(bytecodeOffset + readInt(currentOffset + 1), labels);
1518          currentOffset += 5;
1519          break;
1520        case Constants.WIDE:
1521          switch (classBuffer[currentOffset + 1] & 0xFF) {
1522            case Constants.ILOAD:
1523            case Constants.FLOAD:
1524            case Constants.ALOAD:
1525            case Constants.LLOAD:
1526            case Constants.DLOAD:
1527            case Constants.ISTORE:
1528            case Constants.FSTORE:
1529            case Constants.ASTORE:
1530            case Constants.LSTORE:
1531            case Constants.DSTORE:
1532            case Constants.RET:
1533              currentOffset += 4;
1534              break;
1535            case Constants.IINC:
1536              currentOffset += 6;
1537              break;
1538            default:
1539              throw new IllegalArgumentException();
1540          }
1541          break;
1542        case Constants.TABLESWITCH:
1543          // Skip 0 to 3 padding bytes.
1544          currentOffset += 4 - (bytecodeOffset & 3);
1545          // Read the default label and the number of table entries.
1546          createLabel(bytecodeOffset + readInt(currentOffset), labels);
1547          int numTableEntries = readInt(currentOffset + 8) - readInt(currentOffset + 4) + 1;
1548          currentOffset += 12;
1549          // Read the table labels.
1550          while (numTableEntries-- > 0) {
1551            createLabel(bytecodeOffset + readInt(currentOffset), labels);
1552            currentOffset += 4;
1553          }
1554          break;
1555        case Constants.LOOKUPSWITCH:
1556          // Skip 0 to 3 padding bytes.
1557          currentOffset += 4 - (bytecodeOffset & 3);
1558          // Read the default label and the number of switch cases.
1559          createLabel(bytecodeOffset + readInt(currentOffset), labels);
1560          int numSwitchCases = readInt(currentOffset + 4);
1561          currentOffset += 8;
1562          // Read the switch labels.
1563          while (numSwitchCases-- > 0) {
1564            createLabel(bytecodeOffset + readInt(currentOffset + 4), labels);
1565            currentOffset += 8;
1566          }
1567          break;
1568        case Constants.ILOAD:
1569        case Constants.LLOAD:
1570        case Constants.FLOAD:
1571        case Constants.DLOAD:
1572        case Constants.ALOAD:
1573        case Constants.ISTORE:
1574        case Constants.LSTORE:
1575        case Constants.FSTORE:
1576        case Constants.DSTORE:
1577        case Constants.ASTORE:
1578        case Constants.RET:
1579        case Constants.BIPUSH:
1580        case Constants.NEWARRAY:
1581        case Constants.LDC:
1582          currentOffset += 2;
1583          break;
1584        case Constants.SIPUSH:
1585        case Constants.LDC_W:
1586        case Constants.LDC2_W:
1587        case Constants.GETSTATIC:
1588        case Constants.PUTSTATIC:
1589        case Constants.GETFIELD:
1590        case Constants.PUTFIELD:
1591        case Constants.INVOKEVIRTUAL:
1592        case Constants.INVOKESPECIAL:
1593        case Constants.INVOKESTATIC:
1594        case Constants.NEW:
1595        case Constants.ANEWARRAY:
1596        case Constants.CHECKCAST:
1597        case Constants.INSTANCEOF:
1598        case Constants.IINC:
1599          currentOffset += 3;
1600          break;
1601        case Constants.INVOKEINTERFACE:
1602        case Constants.INVOKEDYNAMIC:
1603          currentOffset += 5;
1604          break;
1605        case Constants.MULTIANEWARRAY:
1606          currentOffset += 4;
1607          break;
1608        default:
1609          throw new IllegalArgumentException();
1610      }
1611    }
1612
1613    // Read the 'exception_table_length' and 'exception_table' field to create a label for each
1614    // referenced instruction, and to make methodVisitor visit the corresponding try catch blocks.
1615    int exceptionTableLength = readUnsignedShort(currentOffset);
1616    currentOffset += 2;
1617    while (exceptionTableLength-- > 0) {
1618      Label start = createLabel(readUnsignedShort(currentOffset), labels);
1619      Label end = createLabel(readUnsignedShort(currentOffset + 2), labels);
1620      Label handler = createLabel(readUnsignedShort(currentOffset + 4), labels);
1621      String catchType = readUTF8(cpInfoOffsets[readUnsignedShort(currentOffset + 6)], charBuffer);
1622      currentOffset += 8;
1623      methodVisitor.visitTryCatchBlock(start, end, handler, catchType);
1624    }
1625
1626    // Read the Code attributes to create a label for each referenced instruction (the variables
1627    // are ordered as in Section 4.7 of the JVMS). Attribute offsets exclude the
1628    // attribute_name_index and attribute_length fields.
1629    // - The offset of the current 'stack_map_frame' in the StackMap[Table] attribute, or 0.
1630    // Initially, this is the offset of the first 'stack_map_frame' entry. Then this offset is
1631    // updated after each stack_map_frame is read.
1632    int stackMapFrameOffset = 0;
1633    // - The end offset of the StackMap[Table] attribute, or 0.
1634    int stackMapTableEndOffset = 0;
1635    // - Whether the stack map frames are compressed (i.e. in a StackMapTable) or not.
1636    boolean compressedFrames = true;
1637    // - The offset of the LocalVariableTable attribute, or 0.
1638    int localVariableTableOffset = 0;
1639    // - The offset of the LocalVariableTypeTable attribute, or 0.
1640    int localVariableTypeTableOffset = 0;
1641    // - The offset of each 'type_annotation' entry in the RuntimeVisibleTypeAnnotations
1642    // attribute, or null.
1643    int[] visibleTypeAnnotationOffsets = null;
1644    // - The offset of each 'type_annotation' entry in the RuntimeInvisibleTypeAnnotations
1645    // attribute, or null.
1646    int[] invisibleTypeAnnotationOffsets = null;
1647    // - The non standard attributes (linked with their {@link Attribute#nextAttribute} field).
1648    //   This list in the <i>reverse order</i> or their order in the ClassFile structure.
1649    Attribute attributes = null;
1650
1651    int attributesCount = readUnsignedShort(currentOffset);
1652    currentOffset += 2;
1653    while (attributesCount-- > 0) {
1654      // Read the attribute_info's attribute_name and attribute_length fields.
1655      String attributeName = readUTF8(currentOffset, charBuffer);
1656      int attributeLength = readInt(currentOffset + 2);
1657      currentOffset += 6;
1658      if (Constants.LOCAL_VARIABLE_TABLE.equals(attributeName)) {
1659        if ((context.parsingOptions & SKIP_DEBUG) == 0) {
1660          localVariableTableOffset = currentOffset;
1661          // Parse the attribute to find the corresponding (debug only) labels.
1662          int currentLocalVariableTableOffset = currentOffset;
1663          int localVariableTableLength = readUnsignedShort(currentLocalVariableTableOffset);
1664          currentLocalVariableTableOffset += 2;
1665          while (localVariableTableLength-- > 0) {
1666            int startPc = readUnsignedShort(currentLocalVariableTableOffset);
1667            createDebugLabel(startPc, labels);
1668            int length = readUnsignedShort(currentLocalVariableTableOffset + 2);
1669            createDebugLabel(startPc + length, labels);
1670            // Skip the name_index, descriptor_index and index fields (2 bytes each).
1671            currentLocalVariableTableOffset += 10;
1672          }
1673        }
1674      } else if (Constants.LOCAL_VARIABLE_TYPE_TABLE.equals(attributeName)) {
1675        localVariableTypeTableOffset = currentOffset;
1676        // Here we do not extract the labels corresponding to the attribute content. We assume they
1677        // are the same or a subset of those of the LocalVariableTable attribute.
1678      } else if (Constants.LINE_NUMBER_TABLE.equals(attributeName)) {
1679        if ((context.parsingOptions & SKIP_DEBUG) == 0) {
1680          // Parse the attribute to find the corresponding (debug only) labels.
1681          int currentLineNumberTableOffset = currentOffset;
1682          int lineNumberTableLength = readUnsignedShort(currentLineNumberTableOffset);
1683          currentLineNumberTableOffset += 2;
1684          while (lineNumberTableLength-- > 0) {
1685            int startPc = readUnsignedShort(currentLineNumberTableOffset);
1686            int lineNumber = readUnsignedShort(currentLineNumberTableOffset + 2);
1687            currentLineNumberTableOffset += 4;
1688            createDebugLabel(startPc, labels);
1689            labels[startPc].addLineNumber(lineNumber);
1690          }
1691        }
1692      } else if (Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1693        visibleTypeAnnotationOffsets =
1694            readTypeAnnotations(methodVisitor, context, currentOffset, /* visible = */ true);
1695        // Here we do not extract the labels corresponding to the attribute content. This would
1696        // require a full parsing of the attribute, which would need to be repeated when parsing
1697        // the bytecode instructions (see below). Instead, the content of the attribute is read one
1698        // type annotation at a time (i.e. after a type annotation has been visited, the next type
1699        // annotation is read), and the labels it contains are also extracted one annotation at a
1700        // time. This assumes that type annotations are ordered by increasing bytecode offset.
1701      } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) {
1702        invisibleTypeAnnotationOffsets =
1703            readTypeAnnotations(methodVisitor, context, currentOffset, /* visible = */ false);
1704        // Same comment as above for the RuntimeVisibleTypeAnnotations attribute.
1705      } else if (Constants.STACK_MAP_TABLE.equals(attributeName)) {
1706        if ((context.parsingOptions & SKIP_FRAMES) == 0) {
1707          stackMapFrameOffset = currentOffset + 2;
1708          stackMapTableEndOffset = currentOffset + attributeLength;
1709        }
1710        // Here we do not extract the labels corresponding to the attribute content. This would
1711        // require a full parsing of the attribute, which would need to be repeated when parsing
1712        // the bytecode instructions (see below). Instead, the content of the attribute is read one
1713        // frame at a time (i.e. after a frame has been visited, the next frame is read), and the
1714        // labels it contains are also extracted one frame at a time. Thanks to the ordering of
1715        // frames, having only a "one frame lookahead" is not a problem, i.e. it is not possible to
1716        // see an offset smaller than the offset of the current instruction and for which no Label
1717        // exist. Except for UNINITIALIZED type offsets. We solve this by parsing the stack map
1718        // table without a full decoding (see below).
1719      } else if ("StackMap".equals(attributeName)) {
1720        if ((context.parsingOptions & SKIP_FRAMES) == 0) {
1721          stackMapFrameOffset = currentOffset + 2;
1722          stackMapTableEndOffset = currentOffset + attributeLength;
1723          compressedFrames = false;
1724        }
1725        // IMPORTANT! Here we assume that the frames are ordered, as in the StackMapTable attribute,
1726        // although this is not guaranteed by the attribute format. This allows an incremental
1727        // extraction of the labels corresponding to this attribute (see the comment above for the
1728        // StackMapTable attribute).
1729      } else {
1730        Attribute attribute =
1731            readAttribute(
1732                context.attributePrototypes,
1733                attributeName,
1734                currentOffset,
1735                attributeLength,
1736                charBuffer,
1737                codeOffset,
1738                labels);
1739        attribute.nextAttribute = attributes;
1740        attributes = attribute;
1741      }
1742      currentOffset += attributeLength;
1743    }
1744
1745    // Initialize the context fields related to stack map frames, and generate the first
1746    // (implicit) stack map frame, if needed.
1747    final boolean expandFrames = (context.parsingOptions & EXPAND_FRAMES) != 0;
1748    if (stackMapFrameOffset != 0) {
1749      // The bytecode offset of the first explicit frame is not offset_delta + 1 but only
1750      // offset_delta. Setting the implicit frame offset to -1 allows us to use of the
1751      // "offset_delta + 1" rule in all cases.
1752      context.currentFrameOffset = -1;
1753      context.currentFrameType = 0;
1754      context.currentFrameLocalCount = 0;
1755      context.currentFrameLocalCountDelta = 0;
1756      context.currentFrameLocalTypes = new Object[maxLocals];
1757      context.currentFrameStackCount = 0;
1758      context.currentFrameStackTypes = new Object[maxStack];
1759      if (expandFrames) {
1760        computeImplicitFrame(context);
1761      }
1762      // Find the labels for UNINITIALIZED frame types. Instead of decoding each element of the
1763      // stack map table, we look for 3 consecutive bytes that "look like" an UNINITIALIZED type
1764      // (tag ITEM_Uninitialized, offset within bytecode bounds, NEW instruction at this offset).
1765      // We may find false positives (i.e. not real UNINITIALIZED types), but this should be rare,
1766      // and the only consequence will be the creation of an unneeded label. This is better than
1767      // creating a label for each NEW instruction, and faster than fully decoding the whole stack
1768      // map table.
1769      for (int offset = stackMapFrameOffset; offset < stackMapTableEndOffset - 2; ++offset) {
1770        if (classBuffer[offset] == Frame.ITEM_UNINITIALIZED) {
1771          int potentialBytecodeOffset = readUnsignedShort(offset + 1);
1772          if (potentialBytecodeOffset >= 0
1773              && potentialBytecodeOffset < codeLength
1774              && (classBuffer[bytecodeStartOffset + potentialBytecodeOffset] & 0xFF)
1775                  == Opcodes.NEW) {
1776            createLabel(potentialBytecodeOffset, labels);
1777          }
1778        }
1779      }
1780    }
1781    if (expandFrames && (context.parsingOptions & EXPAND_ASM_INSNS) != 0) {
1782      // Expanding the ASM specific instructions can introduce F_INSERT frames, even if the method
1783      // does not currently have any frame. These inserted frames must be computed by simulating the
1784      // effect of the bytecode instructions, one by one, starting from the implicit first frame.
1785      // For this, MethodWriter needs to know maxLocals before the first instruction is visited. To
1786      // ensure this, we visit the implicit first frame here (passing only maxLocals - the rest is
1787      // computed in MethodWriter).
1788      methodVisitor.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
1789    }
1790
1791    // Visit the bytecode instructions. First, introduce state variables for the incremental parsing
1792    // of the type annotations.
1793
1794    // Index of the next runtime visible type annotation to read (in the
1795    // visibleTypeAnnotationOffsets array).
1796    int currentVisibleTypeAnnotationIndex = 0;
1797    // The bytecode offset of the next runtime visible type annotation to read, or -1.
1798    int currentVisibleTypeAnnotationBytecodeOffset =
1799        getTypeAnnotationBytecodeOffset(visibleTypeAnnotationOffsets, 0);
1800    // Index of the next runtime invisible type annotation to read (in the
1801    // invisibleTypeAnnotationOffsets array).
1802    int currentInvisibleTypeAnnotationIndex = 0;
1803    // The bytecode offset of the next runtime invisible type annotation to read, or -1.
1804    int currentInvisibleTypeAnnotationBytecodeOffset =
1805        getTypeAnnotationBytecodeOffset(invisibleTypeAnnotationOffsets, 0);
1806
1807    // Whether a F_INSERT stack map frame must be inserted before the current instruction.
1808    boolean insertFrame = false;
1809
1810    // The delta to subtract from a goto_w or jsr_w opcode to get the corresponding goto or jsr
1811    // opcode, or 0 if goto_w and jsr_w must be left unchanged (i.e. when expanding ASM specific
1812    // instructions).
1813    final int wideJumpOpcodeDelta =
1814        (context.parsingOptions & EXPAND_ASM_INSNS) == 0 ? Constants.WIDE_JUMP_OPCODE_DELTA : 0;
1815
1816    currentOffset = bytecodeStartOffset;
1817    while (currentOffset < bytecodeEndOffset) {
1818      final int currentBytecodeOffset = currentOffset - bytecodeStartOffset;
1819
1820      // Visit the label and the line number(s) for this bytecode offset, if any.
1821      Label currentLabel = labels[currentBytecodeOffset];
1822      if (currentLabel != null) {
1823        currentLabel.accept(methodVisitor, (context.parsingOptions & SKIP_DEBUG) == 0);
1824      }
1825
1826      // Visit the stack map frame for this bytecode offset, if any.
1827      while (stackMapFrameOffset != 0
1828          && (context.currentFrameOffset == currentBytecodeOffset
1829              || context.currentFrameOffset == -1)) {
1830        // If there is a stack map frame for this offset, make methodVisitor visit it, and read the
1831        // next stack map frame if there is one.
1832        if (context.currentFrameOffset != -1) {
1833          if (!compressedFrames || expandFrames) {
1834            methodVisitor.visitFrame(
1835                Opcodes.F_NEW,
1836                context.currentFrameLocalCount,
1837                context.currentFrameLocalTypes,
1838                context.currentFrameStackCount,
1839                context.currentFrameStackTypes);
1840          } else {
1841            methodVisitor.visitFrame(
1842                context.currentFrameType,
1843                context.currentFrameLocalCountDelta,
1844                context.currentFrameLocalTypes,
1845                context.currentFrameStackCount,
1846                context.currentFrameStackTypes);
1847          }
1848          // Since there is already a stack map frame for this bytecode offset, there is no need to
1849          // insert a new one.
1850          insertFrame = false;
1851        }
1852        if (stackMapFrameOffset < stackMapTableEndOffset) {
1853          stackMapFrameOffset =
1854              readStackMapFrame(stackMapFrameOffset, compressedFrames, expandFrames, context);
1855        } else {
1856          stackMapFrameOffset = 0;
1857        }
1858      }
1859
1860      // Insert a stack map frame for this bytecode offset, if requested by setting insertFrame to
1861      // true during the previous iteration. The actual frame content is computed in MethodWriter.
1862      if (insertFrame) {
1863        if ((context.parsingOptions & EXPAND_FRAMES) != 0) {
1864          methodVisitor.visitFrame(Constants.F_INSERT, 0, null, 0, null);
1865        }
1866        insertFrame = false;
1867      }
1868
1869      // Visit the instruction at this bytecode offset.
1870      int opcode = classBuffer[currentOffset] & 0xFF;
1871      switch (opcode) {
1872        case Constants.NOP:
1873        case Constants.ACONST_NULL:
1874        case Constants.ICONST_M1:
1875        case Constants.ICONST_0:
1876        case Constants.ICONST_1:
1877        case Constants.ICONST_2:
1878        case Constants.ICONST_3:
1879        case Constants.ICONST_4:
1880        case Constants.ICONST_5:
1881        case Constants.LCONST_0:
1882        case Constants.LCONST_1:
1883        case Constants.FCONST_0:
1884        case Constants.FCONST_1:
1885        case Constants.FCONST_2:
1886        case Constants.DCONST_0:
1887        case Constants.DCONST_1:
1888        case Constants.IALOAD:
1889        case Constants.LALOAD:
1890        case Constants.FALOAD:
1891        case Constants.DALOAD:
1892        case Constants.AALOAD:
1893        case Constants.BALOAD:
1894        case Constants.CALOAD:
1895        case Constants.SALOAD:
1896        case Constants.IASTORE:
1897        case Constants.LASTORE:
1898        case Constants.FASTORE:
1899        case Constants.DASTORE:
1900        case Constants.AASTORE:
1901        case Constants.BASTORE:
1902        case Constants.CASTORE:
1903        case Constants.SASTORE:
1904        case Constants.POP:
1905        case Constants.POP2:
1906        case Constants.DUP:
1907        case Constants.DUP_X1:
1908        case Constants.DUP_X2:
1909        case Constants.DUP2:
1910        case Constants.DUP2_X1:
1911        case Constants.DUP2_X2:
1912        case Constants.SWAP:
1913        case Constants.IADD:
1914        case Constants.LADD:
1915        case Constants.FADD:
1916        case Constants.DADD:
1917        case Constants.ISUB:
1918        case Constants.LSUB:
1919        case Constants.FSUB:
1920        case Constants.DSUB:
1921        case Constants.IMUL:
1922        case Constants.LMUL:
1923        case Constants.FMUL:
1924        case Constants.DMUL:
1925        case Constants.IDIV:
1926        case Constants.LDIV:
1927        case Constants.FDIV:
1928        case Constants.DDIV:
1929        case Constants.IREM:
1930        case Constants.LREM:
1931        case Constants.FREM:
1932        case Constants.DREM:
1933        case Constants.INEG:
1934        case Constants.LNEG:
1935        case Constants.FNEG:
1936        case Constants.DNEG:
1937        case Constants.ISHL:
1938        case Constants.LSHL:
1939        case Constants.ISHR:
1940        case Constants.LSHR:
1941        case Constants.IUSHR:
1942        case Constants.LUSHR:
1943        case Constants.IAND:
1944        case Constants.LAND:
1945        case Constants.IOR:
1946        case Constants.LOR:
1947        case Constants.IXOR:
1948        case Constants.LXOR:
1949        case Constants.I2L:
1950        case Constants.I2F:
1951        case Constants.I2D:
1952        case Constants.L2I:
1953        case Constants.L2F:
1954        case Constants.L2D:
1955        case Constants.F2I:
1956        case Constants.F2L:
1957        case Constants.F2D:
1958        case Constants.D2I:
1959        case Constants.D2L:
1960        case Constants.D2F:
1961        case Constants.I2B:
1962        case Constants.I2C:
1963        case Constants.I2S:
1964        case Constants.LCMP:
1965        case Constants.FCMPL:
1966        case Constants.FCMPG:
1967        case Constants.DCMPL:
1968        case Constants.DCMPG:
1969        case Constants.IRETURN:
1970        case Constants.LRETURN:
1971        case Constants.FRETURN:
1972        case Constants.DRETURN:
1973        case Constants.ARETURN:
1974        case Constants.RETURN:
1975        case Constants.ARRAYLENGTH:
1976        case Constants.ATHROW:
1977        case Constants.MONITORENTER:
1978        case Constants.MONITOREXIT:
1979          methodVisitor.visitInsn(opcode);
1980          currentOffset += 1;
1981          break;
1982        case Constants.ILOAD_0:
1983        case Constants.ILOAD_1:
1984        case Constants.ILOAD_2:
1985        case Constants.ILOAD_3:
1986        case Constants.LLOAD_0:
1987        case Constants.LLOAD_1:
1988        case Constants.LLOAD_2:
1989        case Constants.LLOAD_3:
1990        case Constants.FLOAD_0:
1991        case Constants.FLOAD_1:
1992        case Constants.FLOAD_2:
1993        case Constants.FLOAD_3:
1994        case Constants.DLOAD_0:
1995        case Constants.DLOAD_1:
1996        case Constants.DLOAD_2:
1997        case Constants.DLOAD_3:
1998        case Constants.ALOAD_0:
1999        case Constants.ALOAD_1:
2000        case Constants.ALOAD_2:
2001        case Constants.ALOAD_3:
2002          opcode -= Constants.ILOAD_0;
2003          methodVisitor.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
2004          currentOffset += 1;
2005          break;
2006        case Constants.ISTORE_0:
2007        case Constants.ISTORE_1:
2008        case Constants.ISTORE_2:
2009        case Constants.ISTORE_3:
2010        case Constants.LSTORE_0:
2011        case Constants.LSTORE_1:
2012        case Constants.LSTORE_2:
2013        case Constants.LSTORE_3:
2014        case Constants.FSTORE_0:
2015        case Constants.FSTORE_1:
2016        case Constants.FSTORE_2:
2017        case Constants.FSTORE_3:
2018        case Constants.DSTORE_0:
2019        case Constants.DSTORE_1:
2020        case Constants.DSTORE_2:
2021        case Constants.DSTORE_3:
2022        case Constants.ASTORE_0:
2023        case Constants.ASTORE_1:
2024        case Constants.ASTORE_2:
2025        case Constants.ASTORE_3:
2026          opcode -= Constants.ISTORE_0;
2027          methodVisitor.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), opcode & 0x3);
2028          currentOffset += 1;
2029          break;
2030        case Constants.IFEQ:
2031        case Constants.IFNE:
2032        case Constants.IFLT:
2033        case Constants.IFGE:
2034        case Constants.IFGT:
2035        case Constants.IFLE:
2036        case Constants.IF_ICMPEQ:
2037        case Constants.IF_ICMPNE:
2038        case Constants.IF_ICMPLT:
2039        case Constants.IF_ICMPGE:
2040        case Constants.IF_ICMPGT:
2041        case Constants.IF_ICMPLE:
2042        case Constants.IF_ACMPEQ:
2043        case Constants.IF_ACMPNE:
2044        case Constants.GOTO:
2045        case Constants.JSR:
2046        case Constants.IFNULL:
2047        case Constants.IFNONNULL:
2048          methodVisitor.visitJumpInsn(
2049              opcode, labels[currentBytecodeOffset + readShort(currentOffset + 1)]);
2050          currentOffset += 3;
2051          break;
2052        case Constants.GOTO_W:
2053        case Constants.JSR_W:
2054          methodVisitor.visitJumpInsn(
2055              opcode - wideJumpOpcodeDelta,
2056              labels[currentBytecodeOffset + readInt(currentOffset + 1)]);
2057          currentOffset += 5;
2058          break;
2059        case Constants.ASM_IFEQ:
2060        case Constants.ASM_IFNE:
2061        case Constants.ASM_IFLT:
2062        case Constants.ASM_IFGE:
2063        case Constants.ASM_IFGT:
2064        case Constants.ASM_IFLE:
2065        case Constants.ASM_IF_ICMPEQ:
2066        case Constants.ASM_IF_ICMPNE:
2067        case Constants.ASM_IF_ICMPLT:
2068        case Constants.ASM_IF_ICMPGE:
2069        case Constants.ASM_IF_ICMPGT:
2070        case Constants.ASM_IF_ICMPLE:
2071        case Constants.ASM_IF_ACMPEQ:
2072        case Constants.ASM_IF_ACMPNE:
2073        case Constants.ASM_GOTO:
2074        case Constants.ASM_JSR:
2075        case Constants.ASM_IFNULL:
2076        case Constants.ASM_IFNONNULL:
2077          {
2078            // A forward jump with an offset > 32767. In this case we automatically replace ASM_GOTO
2079            // with GOTO_W, ASM_JSR with JSR_W and ASM_IFxxx <l> with IFNOTxxx <L> GOTO_W <l> L:...,
2080            // where IFNOTxxx is the "opposite" opcode of ASMS_IFxxx (e.g. IFNE for ASM_IFEQ) and
2081            // where <L> designates the instruction just after the GOTO_W.
2082            // First, change the ASM specific opcodes ASM_IFEQ ... ASM_JSR, ASM_IFNULL and
2083            // ASM_IFNONNULL to IFEQ ... JSR, IFNULL and IFNONNULL.
2084            opcode =
2085                opcode < Constants.ASM_IFNULL
2086                    ? opcode - Constants.ASM_OPCODE_DELTA
2087                    : opcode - Constants.ASM_IFNULL_OPCODE_DELTA;
2088            Label target = labels[currentBytecodeOffset + readUnsignedShort(currentOffset + 1)];
2089            if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
2090              // Replace GOTO with GOTO_W and JSR with JSR_W.
2091              methodVisitor.visitJumpInsn(opcode + Constants.WIDE_JUMP_OPCODE_DELTA, target);
2092            } else {
2093              // Compute the "opposite" of opcode. This can be done by flipping the least
2094              // significant bit for IFNULL and IFNONNULL, and similarly for IFEQ ... IF_ACMPEQ
2095              // (with a pre and post offset by 1).
2096              opcode = opcode < Opcodes.GOTO ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1;
2097              Label endif = createLabel(currentBytecodeOffset + 3, labels);
2098              methodVisitor.visitJumpInsn(opcode, endif);
2099              methodVisitor.visitJumpInsn(Constants.GOTO_W, target);
2100              // endif designates the instruction just after GOTO_W, and is visited as part of the
2101              // next instruction. Since it is a jump target, we need to insert a frame here.
2102              insertFrame = true;
2103            }
2104            currentOffset += 3;
2105            break;
2106          }
2107        case Constants.ASM_GOTO_W:
2108          // Replace ASM_GOTO_W with GOTO_W.
2109          methodVisitor.visitJumpInsn(
2110              Constants.GOTO_W, labels[currentBytecodeOffset + readInt(currentOffset + 1)]);
2111          // The instruction just after is a jump target (because ASM_GOTO_W is used in patterns
2112          // IFNOTxxx <L> ASM_GOTO_W <l> L:..., see MethodWriter), so we need to insert a frame
2113          // here.
2114          insertFrame = true;
2115          currentOffset += 5;
2116          break;
2117        case Constants.WIDE:
2118          opcode = classBuffer[currentOffset + 1] & 0xFF;
2119          if (opcode == Opcodes.IINC) {
2120            methodVisitor.visitIincInsn(
2121                readUnsignedShort(currentOffset + 2), readShort(currentOffset + 4));
2122            currentOffset += 6;
2123          } else {
2124            methodVisitor.visitVarInsn(opcode, readUnsignedShort(currentOffset + 2));
2125            currentOffset += 4;
2126          }
2127          break;
2128        case Constants.TABLESWITCH:
2129          {
2130            // Skip 0 to 3 padding bytes.
2131            currentOffset += 4 - (currentBytecodeOffset & 3);
2132            // Read the instruction.
2133            Label defaultLabel = labels[currentBytecodeOffset + readInt(currentOffset)];
2134            int low = readInt(currentOffset + 4);
2135            int high = readInt(currentOffset + 8);
2136            currentOffset += 12;
2137            Label[] table = new Label[high - low + 1];
2138            for (int i = 0; i < table.length; ++i) {
2139              table[i] = labels[currentBytecodeOffset + readInt(currentOffset)];
2140              currentOffset += 4;
2141            }
2142            methodVisitor.visitTableSwitchInsn(low, high, defaultLabel, table);
2143            break;
2144          }
2145        case Constants.LOOKUPSWITCH:
2146          {
2147            // Skip 0 to 3 padding bytes.
2148            currentOffset += 4 - (currentBytecodeOffset & 3);
2149            // Read the instruction.
2150            Label defaultLabel = labels[currentBytecodeOffset + readInt(currentOffset)];
2151            int numPairs = readInt(currentOffset + 4);
2152            currentOffset += 8;
2153            int[] keys = new int[numPairs];
2154            Label[] values = new Label[numPairs];
2155            for (int i = 0; i < numPairs; ++i) {
2156              keys[i] = readInt(currentOffset);
2157              values[i] = labels[currentBytecodeOffset + readInt(currentOffset + 4)];
2158              currentOffset += 8;
2159            }
2160            methodVisitor.visitLookupSwitchInsn(defaultLabel, keys, values);
2161            break;
2162          }
2163        case Constants.ILOAD:
2164        case Constants.LLOAD:
2165        case Constants.FLOAD:
2166        case Constants.DLOAD:
2167        case Constants.ALOAD:
2168        case Constants.ISTORE:
2169        case Constants.LSTORE:
2170        case Constants.FSTORE:
2171        case Constants.DSTORE:
2172        case Constants.ASTORE:
2173        case Constants.RET:
2174          methodVisitor.visitVarInsn(opcode, classBuffer[currentOffset + 1] & 0xFF);
2175          currentOffset += 2;
2176          break;
2177        case Constants.BIPUSH:
2178        case Constants.NEWARRAY:
2179          methodVisitor.visitIntInsn(opcode, classBuffer[currentOffset + 1]);
2180          currentOffset += 2;
2181          break;
2182        case Constants.SIPUSH:
2183          methodVisitor.visitIntInsn(opcode, readShort(currentOffset + 1));
2184          currentOffset += 3;
2185          break;
2186        case Constants.LDC:
2187          methodVisitor.visitLdcInsn(readConst(classBuffer[currentOffset + 1] & 0xFF, charBuffer));
2188          currentOffset += 2;
2189          break;
2190        case Constants.LDC_W:
2191        case Constants.LDC2_W:
2192          methodVisitor.visitLdcInsn(readConst(readUnsignedShort(currentOffset + 1), charBuffer));
2193          currentOffset += 3;
2194          break;
2195        case Constants.GETSTATIC:
2196        case Constants.PUTSTATIC:
2197        case Constants.GETFIELD:
2198        case Constants.PUTFIELD:
2199        case Constants.INVOKEVIRTUAL:
2200        case Constants.INVOKESPECIAL:
2201        case Constants.INVOKESTATIC:
2202        case Constants.INVOKEINTERFACE:
2203          {
2204            int cpInfoOffset = cpInfoOffsets[readUnsignedShort(currentOffset + 1)];
2205            int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
2206            String owner = readClass(cpInfoOffset, charBuffer);
2207            String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
2208            String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
2209            if (opcode < Opcodes.INVOKEVIRTUAL) {
2210              methodVisitor.visitFieldInsn(opcode, owner, name, descriptor);
2211            } else {
2212              boolean isInterface =
2213                  classBuffer[cpInfoOffset - 1] == Symbol.CONSTANT_INTERFACE_METHODREF_TAG;
2214              methodVisitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
2215            }
2216            if (opcode == Opcodes.INVOKEINTERFACE) {
2217              currentOffset += 5;
2218            } else {
2219              currentOffset += 3;
2220            }
2221            break;
2222          }
2223        case Constants.INVOKEDYNAMIC:
2224          {
2225            int cpInfoOffset = cpInfoOffsets[readUnsignedShort(currentOffset + 1)];
2226            int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
2227            String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
2228            String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
2229            int bootstrapMethodOffset = bootstrapMethodOffsets[readUnsignedShort(cpInfoOffset)];
2230            Handle handle =
2231                (Handle) readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
2232            Object[] bootstrapMethodArguments =
2233                new Object[readUnsignedShort(bootstrapMethodOffset + 2)];
2234            bootstrapMethodOffset += 4;
2235            for (int i = 0; i < bootstrapMethodArguments.length; i++) {
2236              bootstrapMethodArguments[i] =
2237                  readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
2238              bootstrapMethodOffset += 2;
2239            }
2240            methodVisitor.visitInvokeDynamicInsn(
2241                name, descriptor, handle, bootstrapMethodArguments);
2242            currentOffset += 5;
2243            break;
2244          }
2245        case Constants.NEW:
2246        case Constants.ANEWARRAY:
2247        case Constants.CHECKCAST:
2248        case Constants.INSTANCEOF:
2249          methodVisitor.visitTypeInsn(opcode, readClass(currentOffset + 1, charBuffer));
2250          currentOffset += 3;
2251          break;
2252        case Constants.IINC:
2253          methodVisitor.visitIincInsn(
2254              classBuffer[currentOffset + 1] & 0xFF, classBuffer[currentOffset + 2]);
2255          currentOffset += 3;
2256          break;
2257        case Constants.MULTIANEWARRAY:
2258          methodVisitor.visitMultiANewArrayInsn(
2259              readClass(currentOffset + 1, charBuffer), classBuffer[currentOffset + 3] & 0xFF);
2260          currentOffset += 4;
2261          break;
2262        default:
2263          throw new AssertionError();
2264      }
2265
2266      // Visit the runtime visible instruction annotations, if any.
2267      while (visibleTypeAnnotationOffsets != null
2268          && currentVisibleTypeAnnotationIndex < visibleTypeAnnotationOffsets.length
2269          && currentVisibleTypeAnnotationBytecodeOffset <= currentBytecodeOffset) {
2270        if (currentVisibleTypeAnnotationBytecodeOffset == currentBytecodeOffset) {
2271          // Parse the target_type, target_info and target_path fields.
2272          int currentAnnotationOffset =
2273              readTypeAnnotationTarget(
2274                  context, visibleTypeAnnotationOffsets[currentVisibleTypeAnnotationIndex]);
2275          // Parse the type_index field.
2276          String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
2277          currentAnnotationOffset += 2;
2278          // Parse num_element_value_pairs and element_value_pairs and visit these values.
2279          readElementValues(
2280              methodVisitor.visitInsnAnnotation(
2281                  context.currentTypeAnnotationTarget,
2282                  context.currentTypeAnnotationTargetPath,
2283                  annotationDescriptor,
2284                  /* visible = */ true),
2285              currentAnnotationOffset,
2286              /* named = */ true,
2287              charBuffer);
2288        }
2289        currentVisibleTypeAnnotationBytecodeOffset =
2290            getTypeAnnotationBytecodeOffset(
2291                visibleTypeAnnotationOffsets, ++currentVisibleTypeAnnotationIndex);
2292      }
2293
2294      // Visit the runtime invisible instruction annotations, if any.
2295      while (invisibleTypeAnnotationOffsets != null
2296          && currentInvisibleTypeAnnotationIndex < invisibleTypeAnnotationOffsets.length
2297          && currentInvisibleTypeAnnotationBytecodeOffset <= currentBytecodeOffset) {
2298        if (currentInvisibleTypeAnnotationBytecodeOffset == currentBytecodeOffset) {
2299          // Parse the target_type, target_info and target_path fields.
2300          int currentAnnotationOffset =
2301              readTypeAnnotationTarget(
2302                  context, invisibleTypeAnnotationOffsets[currentInvisibleTypeAnnotationIndex]);
2303          // Parse the type_index field.
2304          String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
2305          currentAnnotationOffset += 2;
2306          // Parse num_element_value_pairs and element_value_pairs and visit these values.
2307          readElementValues(
2308              methodVisitor.visitInsnAnnotation(
2309                  context.currentTypeAnnotationTarget,
2310                  context.currentTypeAnnotationTargetPath,
2311                  annotationDescriptor,
2312                  /* visible = */ false),
2313              currentAnnotationOffset,
2314              /* named = */ true,
2315              charBuffer);
2316        }
2317        currentInvisibleTypeAnnotationBytecodeOffset =
2318            getTypeAnnotationBytecodeOffset(
2319                invisibleTypeAnnotationOffsets, ++currentInvisibleTypeAnnotationIndex);
2320      }
2321    }
2322    if (labels[codeLength] != null) {
2323      methodVisitor.visitLabel(labels[codeLength]);
2324    }
2325
2326    // Visit LocalVariableTable and LocalVariableTypeTable attributes.
2327    if (localVariableTableOffset != 0 && (context.parsingOptions & SKIP_DEBUG) == 0) {
2328      // The (start_pc, index, signature_index) fields of each entry of the LocalVariableTypeTable.
2329      int[] typeTable = null;
2330      if (localVariableTypeTableOffset != 0) {
2331        typeTable = new int[readUnsignedShort(localVariableTypeTableOffset) * 3];
2332        currentOffset = localVariableTypeTableOffset + 2;
2333        int typeTableIndex = typeTable.length;
2334        while (typeTableIndex > 0) {
2335          // Store the offset of 'signature_index', and the value of 'index' and 'start_pc'.
2336          typeTable[--typeTableIndex] = currentOffset + 6;
2337          typeTable[--typeTableIndex] = readUnsignedShort(currentOffset + 8);
2338          typeTable[--typeTableIndex] = readUnsignedShort(currentOffset);
2339          currentOffset += 10;
2340        }
2341      }
2342      int localVariableTableLength = readUnsignedShort(localVariableTableOffset);
2343      currentOffset = localVariableTableOffset + 2;
2344      while (localVariableTableLength-- > 0) {
2345        int startPc = readUnsignedShort(currentOffset);
2346        int length = readUnsignedShort(currentOffset + 2);
2347        String name = readUTF8(currentOffset + 4, charBuffer);
2348        String descriptor = readUTF8(currentOffset + 6, charBuffer);
2349        int index = readUnsignedShort(currentOffset + 8);
2350        currentOffset += 10;
2351        String signature = null;
2352        if (typeTable != null) {
2353          for (int i = 0; i < typeTable.length; i += 3) {
2354            if (typeTable[i] == startPc && typeTable[i + 1] == index) {
2355              signature = readUTF8(typeTable[i + 2], charBuffer);
2356              break;
2357            }
2358          }
2359        }
2360        methodVisitor.visitLocalVariable(
2361            name, descriptor, signature, labels[startPc], labels[startPc + length], index);
2362      }
2363    }
2364
2365    // Visit the local variable type annotations of the RuntimeVisibleTypeAnnotations attribute.
2366    if (visibleTypeAnnotationOffsets != null) {
2367      for (int typeAnnotationOffset : visibleTypeAnnotationOffsets) {
2368        int targetType = readByte(typeAnnotationOffset);
2369        if (targetType == TypeReference.LOCAL_VARIABLE
2370            || targetType == TypeReference.RESOURCE_VARIABLE) {
2371          // Parse the target_type, target_info and target_path fields.
2372          currentOffset = readTypeAnnotationTarget(context, typeAnnotationOffset);
2373          // Parse the type_index field.
2374          String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2375          currentOffset += 2;
2376          // Parse num_element_value_pairs and element_value_pairs and visit these values.
2377          readElementValues(
2378              methodVisitor.visitLocalVariableAnnotation(
2379                  context.currentTypeAnnotationTarget,
2380                  context.currentTypeAnnotationTargetPath,
2381                  context.currentLocalVariableAnnotationRangeStarts,
2382                  context.currentLocalVariableAnnotationRangeEnds,
2383                  context.currentLocalVariableAnnotationRangeIndices,
2384                  annotationDescriptor,
2385                  /* visible = */ true),
2386              currentOffset,
2387              /* named = */ true,
2388              charBuffer);
2389        }
2390      }
2391    }
2392
2393    // Visit the local variable type annotations of the RuntimeInvisibleTypeAnnotations attribute.
2394    if (invisibleTypeAnnotationOffsets != null) {
2395      for (int typeAnnotationOffset : invisibleTypeAnnotationOffsets) {
2396        int targetType = readByte(typeAnnotationOffset);
2397        if (targetType == TypeReference.LOCAL_VARIABLE
2398            || targetType == TypeReference.RESOURCE_VARIABLE) {
2399          // Parse the target_type, target_info and target_path fields.
2400          currentOffset = readTypeAnnotationTarget(context, typeAnnotationOffset);
2401          // Parse the type_index field.
2402          String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2403          currentOffset += 2;
2404          // Parse num_element_value_pairs and element_value_pairs and visit these values.
2405          readElementValues(
2406              methodVisitor.visitLocalVariableAnnotation(
2407                  context.currentTypeAnnotationTarget,
2408                  context.currentTypeAnnotationTargetPath,
2409                  context.currentLocalVariableAnnotationRangeStarts,
2410                  context.currentLocalVariableAnnotationRangeEnds,
2411                  context.currentLocalVariableAnnotationRangeIndices,
2412                  annotationDescriptor,
2413                  /* visible = */ false),
2414              currentOffset,
2415              /* named = */ true,
2416              charBuffer);
2417        }
2418      }
2419    }
2420
2421    // Visit the non standard attributes.
2422    while (attributes != null) {
2423      // Copy and reset the nextAttribute field so that it can also be used in MethodWriter.
2424      Attribute nextAttribute = attributes.nextAttribute;
2425      attributes.nextAttribute = null;
2426      methodVisitor.visitAttribute(attributes);
2427      attributes = nextAttribute;
2428    }
2429
2430    // Visit the max stack and max locals values.
2431    methodVisitor.visitMaxs(maxStack, maxLocals);
2432  }
2433
2434  /**
2435   * Returns the label corresponding to the given bytecode offset. The default implementation of
2436   * this method creates a label for the given offset if it has not been already created.
2437   *
2438   * @param bytecodeOffset a bytecode offset in a method.
2439   * @param labels the already created labels, indexed by their offset. If a label already exists
2440   *     for bytecodeOffset this method must not create a new one. Otherwise it must store the new
2441   *     label in this array.
2442   * @return a non null Label, which must be equal to labels[bytecodeOffset].
2443   */
2444  protected Label readLabel(final int bytecodeOffset, final Label[] labels) {
2445    if (labels[bytecodeOffset] == null) {
2446      labels[bytecodeOffset] = new Label();
2447    }
2448    return labels[bytecodeOffset];
2449  }
2450
2451  /**
2452   * Creates a label without the {@link Label#FLAG_DEBUG_ONLY} flag set, for the given bytecode
2453   * offset. The label is created with a call to {@link #readLabel} and its {@link
2454   * Label#FLAG_DEBUG_ONLY} flag is cleared.
2455   *
2456   * @param bytecodeOffset a bytecode offset in a method.
2457   * @param labels the already created labels, indexed by their offset.
2458   * @return a Label without the {@link Label#FLAG_DEBUG_ONLY} flag set.
2459   */
2460  private Label createLabel(final int bytecodeOffset, final Label[] labels) {
2461    Label label = readLabel(bytecodeOffset, labels);
2462    label.flags &= ~Label.FLAG_DEBUG_ONLY;
2463    return label;
2464  }
2465
2466  /**
2467   * Creates a label with the {@link Label#FLAG_DEBUG_ONLY} flag set, if there is no already
2468   * existing label for the given bytecode offset (otherwise does nothing). The label is created
2469   * with a call to {@link #readLabel}.
2470   *
2471   * @param bytecodeOffset a bytecode offset in a method.
2472   * @param labels the already created labels, indexed by their offset.
2473   */
2474  private void createDebugLabel(final int bytecodeOffset, final Label[] labels) {
2475    if (labels[bytecodeOffset] == null) {
2476      readLabel(bytecodeOffset, labels).flags |= Label.FLAG_DEBUG_ONLY;
2477    }
2478  }
2479
2480  // ----------------------------------------------------------------------------------------------
2481  // Methods to parse annotations, type annotations and parameter annotations
2482  // ----------------------------------------------------------------------------------------------
2483
2484  /**
2485   * Parses a Runtime[In]VisibleTypeAnnotations attribute to find the offset of each type_annotation
2486   * entry it contains, to find the corresponding labels, and to visit the try catch block
2487   * annotations.
2488   *
2489   * @param methodVisitor the method visitor to be used to visit the try catch block annotations.
2490   * @param context information about the class being parsed.
2491   * @param runtimeTypeAnnotationsOffset the start offset of a Runtime[In]VisibleTypeAnnotations
2492   *     attribute, excluding the attribute_info's attribute_name_index and attribute_length fields.
2493   * @param visible true if the attribute to parse is a RuntimeVisibleTypeAnnotations attribute,
2494   *     false it is a RuntimeInvisibleTypeAnnotations attribute.
2495   * @return the start offset of each entry of the Runtime[In]VisibleTypeAnnotations_attribute's
2496   *     'annotations' array field.
2497   */
2498  private int[] readTypeAnnotations(
2499      final MethodVisitor methodVisitor,
2500      final Context context,
2501      final int runtimeTypeAnnotationsOffset,
2502      final boolean visible) {
2503    char[] charBuffer = context.charBuffer;
2504    int currentOffset = runtimeTypeAnnotationsOffset;
2505    // Read the num_annotations field and create an array to store the type_annotation offsets.
2506    int[] typeAnnotationsOffsets = new int[readUnsignedShort(currentOffset)];
2507    currentOffset += 2;
2508    // Parse the 'annotations' array field.
2509    for (int i = 0; i < typeAnnotationsOffsets.length; ++i) {
2510      typeAnnotationsOffsets[i] = currentOffset;
2511      // Parse the type_annotation's target_type and the target_info fields. The size of the
2512      // target_info field depends on the value of target_type.
2513      int targetType = readInt(currentOffset);
2514      switch (targetType >>> 24) {
2515        case TypeReference.LOCAL_VARIABLE:
2516        case TypeReference.RESOURCE_VARIABLE:
2517          // A localvar_target has a variable size, which depends on the value of their table_length
2518          // field. It also references bytecode offsets, for which we need labels.
2519          int tableLength = readUnsignedShort(currentOffset + 1);
2520          currentOffset += 3;
2521          while (tableLength-- > 0) {
2522            int startPc = readUnsignedShort(currentOffset);
2523            int length = readUnsignedShort(currentOffset + 2);
2524            // Skip the index field (2 bytes).
2525            currentOffset += 6;
2526            createLabel(startPc, context.currentMethodLabels);
2527            createLabel(startPc + length, context.currentMethodLabels);
2528          }
2529          break;
2530        case TypeReference.CAST:
2531        case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
2532        case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
2533        case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
2534        case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
2535          currentOffset += 4;
2536          break;
2537        case TypeReference.CLASS_EXTENDS:
2538        case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
2539        case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
2540        case TypeReference.THROWS:
2541        case TypeReference.EXCEPTION_PARAMETER:
2542        case TypeReference.INSTANCEOF:
2543        case TypeReference.NEW:
2544        case TypeReference.CONSTRUCTOR_REFERENCE:
2545        case TypeReference.METHOD_REFERENCE:
2546          currentOffset += 3;
2547          break;
2548        case TypeReference.CLASS_TYPE_PARAMETER:
2549        case TypeReference.METHOD_TYPE_PARAMETER:
2550        case TypeReference.METHOD_FORMAL_PARAMETER:
2551        case TypeReference.FIELD:
2552        case TypeReference.METHOD_RETURN:
2553        case TypeReference.METHOD_RECEIVER:
2554        default:
2555          // TypeReference type which can't be used in Code attribute, or which is unknown.
2556          throw new IllegalArgumentException();
2557      }
2558      // Parse the rest of the type_annotation structure, starting with the target_path structure
2559      // (whose size depends on its path_length field).
2560      int pathLength = readByte(currentOffset);
2561      if ((targetType >>> 24) == TypeReference.EXCEPTION_PARAMETER) {
2562        // Parse the target_path structure and create a corresponding TypePath.
2563        TypePath path = pathLength == 0 ? null : new TypePath(classFileBuffer, currentOffset);
2564        currentOffset += 1 + 2 * pathLength;
2565        // Parse the type_index field.
2566        String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2567        currentOffset += 2;
2568        // Parse num_element_value_pairs and element_value_pairs and visit these values.
2569        currentOffset =
2570            readElementValues(
2571                methodVisitor.visitTryCatchAnnotation(
2572                    targetType & 0xFFFFFF00, path, annotationDescriptor, visible),
2573                currentOffset,
2574                /* named = */ true,
2575                charBuffer);
2576      } else {
2577        // We don't want to visit the other target_type annotations, so we just skip them (which
2578        // requires some parsing because the element_value_pairs array has a variable size). First,
2579        // skip the target_path structure:
2580        currentOffset += 3 + 2 * pathLength;
2581        // Then skip the num_element_value_pairs and element_value_pairs fields (by reading them
2582        // with a null AnnotationVisitor).
2583        currentOffset =
2584            readElementValues(
2585                /* annotationVisitor = */ null, currentOffset, /* named = */ true, charBuffer);
2586      }
2587    }
2588    return typeAnnotationsOffsets;
2589  }
2590
2591  /**
2592   * Returns the bytecode offset corresponding to the specified JVMS 'type_annotation' structure, or
2593   * -1 if there is no such type_annotation of if it does not have a bytecode offset.
2594   *
2595   * @param typeAnnotationOffsets the offset of each 'type_annotation' entry in a
2596   *     Runtime[In]VisibleTypeAnnotations attribute, or null.
2597   * @param typeAnnotationIndex the index a 'type_annotation' entry in typeAnnotationOffsets.
2598   * @return bytecode offset corresponding to the specified JVMS 'type_annotation' structure, or -1
2599   *     if there is no such type_annotation of if it does not have a bytecode offset.
2600   */
2601  private int getTypeAnnotationBytecodeOffset(
2602      final int[] typeAnnotationOffsets, final int typeAnnotationIndex) {
2603    if (typeAnnotationOffsets == null
2604        || typeAnnotationIndex >= typeAnnotationOffsets.length
2605        || readByte(typeAnnotationOffsets[typeAnnotationIndex]) < TypeReference.INSTANCEOF) {
2606      return -1;
2607    }
2608    return readUnsignedShort(typeAnnotationOffsets[typeAnnotationIndex] + 1);
2609  }
2610
2611  /**
2612   * Parses the header of a JVMS type_annotation structure to extract its target_type, target_info
2613   * and target_path (the result is stored in the given context), and returns the start offset of
2614   * the rest of the type_annotation structure.
2615   *
2616   * @param context information about the class being parsed. This is where the extracted
2617   *     target_type and target_path must be stored.
2618   * @param typeAnnotationOffset the start offset of a type_annotation structure.
2619   * @return the start offset of the rest of the type_annotation structure.
2620   */
2621  private int readTypeAnnotationTarget(final Context context, final int typeAnnotationOffset) {
2622    int currentOffset = typeAnnotationOffset;
2623    // Parse and store the target_type structure.
2624    int targetType = readInt(typeAnnotationOffset);
2625    switch (targetType >>> 24) {
2626      case TypeReference.CLASS_TYPE_PARAMETER:
2627      case TypeReference.METHOD_TYPE_PARAMETER:
2628      case TypeReference.METHOD_FORMAL_PARAMETER:
2629        targetType &= 0xFFFF0000;
2630        currentOffset += 2;
2631        break;
2632      case TypeReference.FIELD:
2633      case TypeReference.METHOD_RETURN:
2634      case TypeReference.METHOD_RECEIVER:
2635        targetType &= 0xFF000000;
2636        currentOffset += 1;
2637        break;
2638      case TypeReference.LOCAL_VARIABLE:
2639      case TypeReference.RESOURCE_VARIABLE:
2640        targetType &= 0xFF000000;
2641        int tableLength = readUnsignedShort(currentOffset + 1);
2642        currentOffset += 3;
2643        context.currentLocalVariableAnnotationRangeStarts = new Label[tableLength];
2644        context.currentLocalVariableAnnotationRangeEnds = new Label[tableLength];
2645        context.currentLocalVariableAnnotationRangeIndices = new int[tableLength];
2646        for (int i = 0; i < tableLength; ++i) {
2647          int startPc = readUnsignedShort(currentOffset);
2648          int length = readUnsignedShort(currentOffset + 2);
2649          int index = readUnsignedShort(currentOffset + 4);
2650          currentOffset += 6;
2651          context.currentLocalVariableAnnotationRangeStarts[i] =
2652              createLabel(startPc, context.currentMethodLabels);
2653          context.currentLocalVariableAnnotationRangeEnds[i] =
2654              createLabel(startPc + length, context.currentMethodLabels);
2655          context.currentLocalVariableAnnotationRangeIndices[i] = index;
2656        }
2657        break;
2658      case TypeReference.CAST:
2659      case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
2660      case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
2661      case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
2662      case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
2663        targetType &= 0xFF0000FF;
2664        currentOffset += 4;
2665        break;
2666      case TypeReference.CLASS_EXTENDS:
2667      case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
2668      case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
2669      case TypeReference.THROWS:
2670      case TypeReference.EXCEPTION_PARAMETER:
2671        targetType &= 0xFFFFFF00;
2672        currentOffset += 3;
2673        break;
2674      case TypeReference.INSTANCEOF:
2675      case TypeReference.NEW:
2676      case TypeReference.CONSTRUCTOR_REFERENCE:
2677      case TypeReference.METHOD_REFERENCE:
2678        targetType &= 0xFF000000;
2679        currentOffset += 3;
2680        break;
2681      default:
2682        throw new IllegalArgumentException();
2683    }
2684    context.currentTypeAnnotationTarget = targetType;
2685    // Parse and store the target_path structure.
2686    int pathLength = readByte(currentOffset);
2687    context.currentTypeAnnotationTargetPath =
2688        pathLength == 0 ? null : new TypePath(classFileBuffer, currentOffset);
2689    // Return the start offset of the rest of the type_annotation structure.
2690    return currentOffset + 1 + 2 * pathLength;
2691  }
2692
2693  /**
2694   * Reads a Runtime[In]VisibleParameterAnnotations attribute and makes the given visitor visit it.
2695   *
2696   * @param methodVisitor the visitor that must visit the parameter annotations.
2697   * @param context information about the class being parsed.
2698   * @param runtimeParameterAnnotationsOffset the start offset of a
2699   *     Runtime[In]VisibleParameterAnnotations attribute, excluding the attribute_info's
2700   *     attribute_name_index and attribute_length fields.
2701   * @param visible true if the attribute to parse is a RuntimeVisibleParameterAnnotations
2702   *     attribute, false it is a RuntimeInvisibleParameterAnnotations attribute.
2703   */
2704  private void readParameterAnnotations(
2705      final MethodVisitor methodVisitor,
2706      final Context context,
2707      final int runtimeParameterAnnotationsOffset,
2708      final boolean visible) {
2709    int currentOffset = runtimeParameterAnnotationsOffset;
2710    int numParameters = classFileBuffer[currentOffset++] & 0xFF;
2711    methodVisitor.visitAnnotableParameterCount(numParameters, visible);
2712    char[] charBuffer = context.charBuffer;
2713    for (int i = 0; i < numParameters; ++i) {
2714      int numAnnotations = readUnsignedShort(currentOffset);
2715      currentOffset += 2;
2716      while (numAnnotations-- > 0) {
2717        // Parse the type_index field.
2718        String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2719        currentOffset += 2;
2720        // Parse num_element_value_pairs and element_value_pairs and visit these values.
2721        currentOffset =
2722            readElementValues(
2723                methodVisitor.visitParameterAnnotation(i, annotationDescriptor, visible),
2724                currentOffset,
2725                /* named = */ true,
2726                charBuffer);
2727      }
2728    }
2729  }
2730
2731  /**
2732   * Reads the element values of a JVMS 'annotation' structure and makes the given visitor visit
2733   * them. This method can also be used to read the values of the JVMS 'array_value' field of an
2734   * annotation's 'element_value'.
2735   *
2736   * @param annotationVisitor the visitor that must visit the values.
2737   * @param annotationOffset the start offset of an 'annotation' structure (excluding its type_index
2738   *     field) or of an 'array_value' structure.
2739   * @param named if the annotation values are named or not. This should be true to parse the values
2740   *     of a JVMS 'annotation' structure, and false to parse the JVMS 'array_value' of an
2741   *     annotation's element_value.
2742   * @param charBuffer the buffer used to read strings in the constant pool.
2743   * @return the end offset of the JVMS 'annotation' or 'array_value' structure.
2744   */
2745  private int readElementValues(
2746      final AnnotationVisitor annotationVisitor,
2747      final int annotationOffset,
2748      final boolean named,
2749      final char[] charBuffer) {
2750    int currentOffset = annotationOffset;
2751    // Read the num_element_value_pairs field (or num_values field for an array_value).
2752    int numElementValuePairs = readUnsignedShort(currentOffset);
2753    currentOffset += 2;
2754    if (named) {
2755      // Parse the element_value_pairs array.
2756      while (numElementValuePairs-- > 0) {
2757        String elementName = readUTF8(currentOffset, charBuffer);
2758        currentOffset =
2759            readElementValue(annotationVisitor, currentOffset + 2, elementName, charBuffer);
2760      }
2761    } else {
2762      // Parse the array_value array.
2763      while (numElementValuePairs-- > 0) {
2764        currentOffset =
2765            readElementValue(annotationVisitor, currentOffset, /* named = */ null, charBuffer);
2766      }
2767    }
2768    if (annotationVisitor != null) {
2769      annotationVisitor.visitEnd();
2770    }
2771    return currentOffset;
2772  }
2773
2774  /**
2775   * Reads a JVMS 'element_value' structure and makes the given visitor visit it.
2776   *
2777   * @param annotationVisitor the visitor that must visit the element_value structure.
2778   * @param elementValueOffset the start offset in {@link #classFileBuffer} of the element_value
2779   *     structure to be read.
2780   * @param elementName the name of the element_value structure to be read, or {@literal null}.
2781   * @param charBuffer the buffer used to read strings in the constant pool.
2782   * @return the end offset of the JVMS 'element_value' structure.
2783   */
2784  private int readElementValue(
2785      final AnnotationVisitor annotationVisitor,
2786      final int elementValueOffset,
2787      final String elementName,
2788      final char[] charBuffer) {
2789    int currentOffset = elementValueOffset;
2790    if (annotationVisitor == null) {
2791      switch (classFileBuffer[currentOffset] & 0xFF) {
2792        case 'e': // enum_const_value
2793          return currentOffset + 5;
2794        case '@': // annotation_value
2795          return readElementValues(null, currentOffset + 3, /* named = */ true, charBuffer);
2796        case '[': // array_value
2797          return readElementValues(null, currentOffset + 1, /* named = */ false, charBuffer);
2798        default:
2799          return currentOffset + 3;
2800      }
2801    }
2802    switch (classFileBuffer[currentOffset++] & 0xFF) {
2803      case 'B': // const_value_index, CONSTANT_Integer
2804        annotationVisitor.visit(
2805            elementName, (byte) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
2806        currentOffset += 2;
2807        break;
2808      case 'C': // const_value_index, CONSTANT_Integer
2809        annotationVisitor.visit(
2810            elementName, (char) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
2811        currentOffset += 2;
2812        break;
2813      case 'D': // const_value_index, CONSTANT_Double
2814      case 'F': // const_value_index, CONSTANT_Float
2815      case 'I': // const_value_index, CONSTANT_Integer
2816      case 'J': // const_value_index, CONSTANT_Long
2817        annotationVisitor.visit(
2818            elementName, readConst(readUnsignedShort(currentOffset), charBuffer));
2819        currentOffset += 2;
2820        break;
2821      case 'S': // const_value_index, CONSTANT_Integer
2822        annotationVisitor.visit(
2823            elementName, (short) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
2824        currentOffset += 2;
2825        break;
2826
2827      case 'Z': // const_value_index, CONSTANT_Integer
2828        annotationVisitor.visit(
2829            elementName,
2830            readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]) == 0
2831                ? Boolean.FALSE
2832                : Boolean.TRUE);
2833        currentOffset += 2;
2834        break;
2835      case 's': // const_value_index, CONSTANT_Utf8
2836        annotationVisitor.visit(elementName, readUTF8(currentOffset, charBuffer));
2837        currentOffset += 2;
2838        break;
2839      case 'e': // enum_const_value
2840        annotationVisitor.visitEnum(
2841            elementName,
2842            readUTF8(currentOffset, charBuffer),
2843            readUTF8(currentOffset + 2, charBuffer));
2844        currentOffset += 4;
2845        break;
2846      case 'c': // class_info
2847        annotationVisitor.visit(elementName, Type.getType(readUTF8(currentOffset, charBuffer)));
2848        currentOffset += 2;
2849        break;
2850      case '@': // annotation_value
2851        currentOffset =
2852            readElementValues(
2853                annotationVisitor.visitAnnotation(elementName, readUTF8(currentOffset, charBuffer)),
2854                currentOffset + 2,
2855                true,
2856                charBuffer);
2857        break;
2858      case '[': // array_value
2859        int numValues = readUnsignedShort(currentOffset);
2860        currentOffset += 2;
2861        if (numValues == 0) {
2862          return readElementValues(
2863              annotationVisitor.visitArray(elementName),
2864              currentOffset - 2,
2865              /* named = */ false,
2866              charBuffer);
2867        }
2868        switch (classFileBuffer[currentOffset] & 0xFF) {
2869          case 'B':
2870            byte[] byteValues = new byte[numValues];
2871            for (int i = 0; i < numValues; i++) {
2872              byteValues[i] = (byte) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
2873              currentOffset += 3;
2874            }
2875            annotationVisitor.visit(elementName, byteValues);
2876            break;
2877          case 'Z':
2878            boolean[] booleanValues = new boolean[numValues];
2879            for (int i = 0; i < numValues; i++) {
2880              booleanValues[i] = readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]) != 0;
2881              currentOffset += 3;
2882            }
2883            annotationVisitor.visit(elementName, booleanValues);
2884            break;
2885          case 'S':
2886            short[] shortValues = new short[numValues];
2887            for (int i = 0; i < numValues; i++) {
2888              shortValues[i] = (short) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
2889              currentOffset += 3;
2890            }
2891            annotationVisitor.visit(elementName, shortValues);
2892            break;
2893          case 'C':
2894            char[] charValues = new char[numValues];
2895            for (int i = 0; i < numValues; i++) {
2896              charValues[i] = (char) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
2897              currentOffset += 3;
2898            }
2899            annotationVisitor.visit(elementName, charValues);
2900            break;
2901          case 'I':
2902            int[] intValues = new int[numValues];
2903            for (int i = 0; i < numValues; i++) {
2904              intValues[i] = readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
2905              currentOffset += 3;
2906            }
2907            annotationVisitor.visit(elementName, intValues);
2908            break;
2909          case 'J':
2910            long[] longValues = new long[numValues];
2911            for (int i = 0; i < numValues; i++) {
2912              longValues[i] = readLong(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
2913              currentOffset += 3;
2914            }
2915            annotationVisitor.visit(elementName, longValues);
2916            break;
2917          case 'F':
2918            float[] floatValues = new float[numValues];
2919            for (int i = 0; i < numValues; i++) {
2920              floatValues[i] =
2921                  Float.intBitsToFloat(
2922                      readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]));
2923              currentOffset += 3;
2924            }
2925            annotationVisitor.visit(elementName, floatValues);
2926            break;
2927          case 'D':
2928            double[] doubleValues = new double[numValues];
2929            for (int i = 0; i < numValues; i++) {
2930              doubleValues[i] =
2931                  Double.longBitsToDouble(
2932                      readLong(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]));
2933              currentOffset += 3;
2934            }
2935            annotationVisitor.visit(elementName, doubleValues);
2936            break;
2937          default:
2938            currentOffset =
2939                readElementValues(
2940                    annotationVisitor.visitArray(elementName),
2941                    currentOffset - 2,
2942                    /* named = */ false,
2943                    charBuffer);
2944            break;
2945        }
2946        break;
2947      default:
2948        throw new IllegalArgumentException();
2949    }
2950    return currentOffset;
2951  }
2952
2953  // ----------------------------------------------------------------------------------------------
2954  // Methods to parse stack map frames
2955  // ----------------------------------------------------------------------------------------------
2956
2957  /**
2958   * Computes the implicit frame of the method currently being parsed (as defined in the given
2959   * {@link Context}) and stores it in the given context.
2960   *
2961   * @param context information about the class being parsed.
2962   */
2963  private void computeImplicitFrame(final Context context) {
2964    String methodDescriptor = context.currentMethodDescriptor;
2965    Object[] locals = context.currentFrameLocalTypes;
2966    int numLocal = 0;
2967    if ((context.currentMethodAccessFlags & Opcodes.ACC_STATIC) == 0) {
2968      if ("<init>".equals(context.currentMethodName)) {
2969        locals[numLocal++] = Opcodes.UNINITIALIZED_THIS;
2970      } else {
2971        locals[numLocal++] = readClass(header + 2, context.charBuffer);
2972      }
2973    }
2974    // Parse the method descriptor, one argument type descriptor at each iteration. Start by
2975    // skipping the first method descriptor character, which is always '('.
2976    int currentMethodDescritorOffset = 1;
2977    while (true) {
2978      int currentArgumentDescriptorStartOffset = currentMethodDescritorOffset;
2979      switch (methodDescriptor.charAt(currentMethodDescritorOffset++)) {
2980        case 'Z':
2981        case 'C':
2982        case 'B':
2983        case 'S':
2984        case 'I':
2985          locals[numLocal++] = Opcodes.INTEGER;
2986          break;
2987        case 'F':
2988          locals[numLocal++] = Opcodes.FLOAT;
2989          break;
2990        case 'J':
2991          locals[numLocal++] = Opcodes.LONG;
2992          break;
2993        case 'D':
2994          locals[numLocal++] = Opcodes.DOUBLE;
2995          break;
2996        case '[':
2997          while (methodDescriptor.charAt(currentMethodDescritorOffset) == '[') {
2998            ++currentMethodDescritorOffset;
2999          }
3000          if (methodDescriptor.charAt(currentMethodDescritorOffset) == 'L') {
3001            ++currentMethodDescritorOffset;
3002            while (methodDescriptor.charAt(currentMethodDescritorOffset) != ';') {
3003              ++currentMethodDescritorOffset;
3004            }
3005          }
3006          locals[numLocal++] =
3007              methodDescriptor.substring(
3008                  currentArgumentDescriptorStartOffset, ++currentMethodDescritorOffset);
3009          break;
3010        case 'L':
3011          while (methodDescriptor.charAt(currentMethodDescritorOffset) != ';') {
3012            ++currentMethodDescritorOffset;
3013          }
3014          locals[numLocal++] =
3015              methodDescriptor.substring(
3016                  currentArgumentDescriptorStartOffset + 1, currentMethodDescritorOffset++);
3017          break;
3018        default:
3019          context.currentFrameLocalCount = numLocal;
3020          return;
3021      }
3022    }
3023  }
3024
3025  /**
3026   * Reads a JVMS 'stack_map_frame' structure and stores the result in the given {@link Context}
3027   * object. This method can also be used to read a full_frame structure, excluding its frame_type
3028   * field (this is used to parse the legacy StackMap attributes).
3029   *
3030   * @param stackMapFrameOffset the start offset in {@link #classFileBuffer} of the
3031   *     stack_map_frame_value structure to be read, or the start offset of a full_frame structure
3032   *     (excluding its frame_type field).
3033   * @param compressed true to read a 'stack_map_frame' structure, false to read a 'full_frame'
3034   *     structure without its frame_type field.
3035   * @param expand if the stack map frame must be expanded. See {@link #EXPAND_FRAMES}.
3036   * @param context where the parsed stack map frame must be stored.
3037   * @return the end offset of the JVMS 'stack_map_frame' or 'full_frame' structure.
3038   */
3039  private int readStackMapFrame(
3040      final int stackMapFrameOffset,
3041      final boolean compressed,
3042      final boolean expand,
3043      final Context context) {
3044    int currentOffset = stackMapFrameOffset;
3045    final char[] charBuffer = context.charBuffer;
3046    final Label[] labels = context.currentMethodLabels;
3047    int frameType;
3048    if (compressed) {
3049      // Read the frame_type field.
3050      frameType = classFileBuffer[currentOffset++] & 0xFF;
3051    } else {
3052      frameType = Frame.FULL_FRAME;
3053      context.currentFrameOffset = -1;
3054    }
3055    int offsetDelta;
3056    context.currentFrameLocalCountDelta = 0;
3057    if (frameType < Frame.SAME_LOCALS_1_STACK_ITEM_FRAME) {
3058      offsetDelta = frameType;
3059      context.currentFrameType = Opcodes.F_SAME;
3060      context.currentFrameStackCount = 0;
3061    } else if (frameType < Frame.RESERVED) {
3062      offsetDelta = frameType - Frame.SAME_LOCALS_1_STACK_ITEM_FRAME;
3063      currentOffset =
3064          readVerificationTypeInfo(
3065              currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels);
3066      context.currentFrameType = Opcodes.F_SAME1;
3067      context.currentFrameStackCount = 1;
3068    } else if (frameType >= Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
3069      offsetDelta = readUnsignedShort(currentOffset);
3070      currentOffset += 2;
3071      if (frameType == Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
3072        currentOffset =
3073            readVerificationTypeInfo(
3074                currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels);
3075        context.currentFrameType = Opcodes.F_SAME1;
3076        context.currentFrameStackCount = 1;
3077      } else if (frameType >= Frame.CHOP_FRAME && frameType < Frame.SAME_FRAME_EXTENDED) {
3078        context.currentFrameType = Opcodes.F_CHOP;
3079        context.currentFrameLocalCountDelta = Frame.SAME_FRAME_EXTENDED - frameType;
3080        context.currentFrameLocalCount -= context.currentFrameLocalCountDelta;
3081        context.currentFrameStackCount = 0;
3082      } else if (frameType == Frame.SAME_FRAME_EXTENDED) {
3083        context.currentFrameType = Opcodes.F_SAME;
3084        context.currentFrameStackCount = 0;
3085      } else if (frameType < Frame.FULL_FRAME) {
3086        int local = expand ? context.currentFrameLocalCount : 0;
3087        for (int k = frameType - Frame.SAME_FRAME_EXTENDED; k > 0; k--) {
3088          currentOffset =
3089              readVerificationTypeInfo(
3090                  currentOffset, context.currentFrameLocalTypes, local++, charBuffer, labels);
3091        }
3092        context.currentFrameType = Opcodes.F_APPEND;
3093        context.currentFrameLocalCountDelta = frameType - Frame.SAME_FRAME_EXTENDED;
3094        context.currentFrameLocalCount += context.currentFrameLocalCountDelta;
3095        context.currentFrameStackCount = 0;
3096      } else {
3097        final int numberOfLocals = readUnsignedShort(currentOffset);
3098        currentOffset += 2;
3099        context.currentFrameType = Opcodes.F_FULL;
3100        context.currentFrameLocalCountDelta = numberOfLocals;
3101        context.currentFrameLocalCount = numberOfLocals;
3102        for (int local = 0; local < numberOfLocals; ++local) {
3103          currentOffset =
3104              readVerificationTypeInfo(
3105                  currentOffset, context.currentFrameLocalTypes, local, charBuffer, labels);
3106        }
3107        final int numberOfStackItems = readUnsignedShort(currentOffset);
3108        currentOffset += 2;
3109        context.currentFrameStackCount = numberOfStackItems;
3110        for (int stack = 0; stack < numberOfStackItems; ++stack) {
3111          currentOffset =
3112              readVerificationTypeInfo(
3113                  currentOffset, context.currentFrameStackTypes, stack, charBuffer, labels);
3114        }
3115      }
3116    } else {
3117      throw new IllegalArgumentException();
3118    }
3119    context.currentFrameOffset += offsetDelta + 1;
3120    createLabel(context.currentFrameOffset, labels);
3121    return currentOffset;
3122  }
3123
3124  /**
3125   * Reads a JVMS 'verification_type_info' structure and stores it at the given index in the given
3126   * array.
3127   *
3128   * @param verificationTypeInfoOffset the start offset of the 'verification_type_info' structure to
3129   *     read.
3130   * @param frame the array where the parsed type must be stored.
3131   * @param index the index in 'frame' where the parsed type must be stored.
3132   * @param charBuffer the buffer used to read strings in the constant pool.
3133   * @param labels the labels of the method currently being parsed, indexed by their offset. If the
3134   *     parsed type is an ITEM_Uninitialized, a new label for the corresponding NEW instruction is
3135   *     stored in this array if it does not already exist.
3136   * @return the end offset of the JVMS 'verification_type_info' structure.
3137   */
3138  private int readVerificationTypeInfo(
3139      final int verificationTypeInfoOffset,
3140      final Object[] frame,
3141      final int index,
3142      final char[] charBuffer,
3143      final Label[] labels) {
3144    int currentOffset = verificationTypeInfoOffset;
3145    int tag = classFileBuffer[currentOffset++] & 0xFF;
3146    switch (tag) {
3147      case Frame.ITEM_TOP:
3148        frame[index] = Opcodes.TOP;
3149        break;
3150      case Frame.ITEM_INTEGER:
3151        frame[index] = Opcodes.INTEGER;
3152        break;
3153      case Frame.ITEM_FLOAT:
3154        frame[index] = Opcodes.FLOAT;
3155        break;
3156      case Frame.ITEM_DOUBLE:
3157        frame[index] = Opcodes.DOUBLE;
3158        break;
3159      case Frame.ITEM_LONG:
3160        frame[index] = Opcodes.LONG;
3161        break;
3162      case Frame.ITEM_NULL:
3163        frame[index] = Opcodes.NULL;
3164        break;
3165      case Frame.ITEM_UNINITIALIZED_THIS:
3166        frame[index] = Opcodes.UNINITIALIZED_THIS;
3167        break;
3168      case Frame.ITEM_OBJECT:
3169        frame[index] = readClass(currentOffset, charBuffer);
3170        currentOffset += 2;
3171        break;
3172      case Frame.ITEM_UNINITIALIZED:
3173        frame[index] = createLabel(readUnsignedShort(currentOffset), labels);
3174        currentOffset += 2;
3175        break;
3176      default:
3177        throw new IllegalArgumentException();
3178    }
3179    return currentOffset;
3180  }
3181
3182  // ----------------------------------------------------------------------------------------------
3183  // Methods to parse attributes
3184  // ----------------------------------------------------------------------------------------------
3185
3186  /**
3187   * Returns the offset in {@link #classFileBuffer} of the first ClassFile's 'attributes' array
3188   * field entry.
3189   *
3190   * @return the offset in {@link #classFileBuffer} of the first ClassFile's 'attributes' array
3191   *     field entry.
3192   */
3193  final int getFirstAttributeOffset() {
3194    // Skip the access_flags, this_class, super_class, and interfaces_count fields (using 2 bytes
3195    // each), as well as the interfaces array field (2 bytes per interface).
3196    int currentOffset = header + 8 + readUnsignedShort(header + 6) * 2;
3197
3198    // Read the fields_count field.
3199    int fieldsCount = readUnsignedShort(currentOffset);
3200    currentOffset += 2;
3201    // Skip the 'fields' array field.
3202    while (fieldsCount-- > 0) {
3203      // Invariant: currentOffset is the offset of a field_info structure.
3204      // Skip the access_flags, name_index and descriptor_index fields (2 bytes each), and read the
3205      // attributes_count field.
3206      int attributesCount = readUnsignedShort(currentOffset + 6);
3207      currentOffset += 8;
3208      // Skip the 'attributes' array field.
3209      while (attributesCount-- > 0) {
3210        // Invariant: currentOffset is the offset of an attribute_info structure.
3211        // Read the attribute_length field (2 bytes after the start of the attribute_info) and skip
3212        // this many bytes, plus 6 for the attribute_name_index and attribute_length fields
3213        // (yielding the total size of the attribute_info structure).
3214        currentOffset += 6 + readInt(currentOffset + 2);
3215      }
3216    }
3217
3218    // Skip the methods_count and 'methods' fields, using the same method as above.
3219    int methodsCount = readUnsignedShort(currentOffset);
3220    currentOffset += 2;
3221    while (methodsCount-- > 0) {
3222      int attributesCount = readUnsignedShort(currentOffset + 6);
3223      currentOffset += 8;
3224      while (attributesCount-- > 0) {
3225        currentOffset += 6 + readInt(currentOffset + 2);
3226      }
3227    }
3228
3229    // Skip the ClassFile's attributes_count field.
3230    return currentOffset + 2;
3231  }
3232
3233  /**
3234   * Reads the BootstrapMethods attribute to compute the offset of each bootstrap method.
3235   *
3236   * @param maxStringLength a conservative estimate of the maximum length of the strings contained
3237   *     in the constant pool of the class.
3238   * @return the offsets of the bootstrap methods.
3239   */
3240  private int[] readBootstrapMethodsAttribute(final int maxStringLength) {
3241    char[] charBuffer = new char[maxStringLength];
3242    int currentAttributeOffset = getFirstAttributeOffset();
3243    int[] currentBootstrapMethodOffsets = null;
3244    for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) {
3245      // Read the attribute_info's attribute_name and attribute_length fields.
3246      String attributeName = readUTF8(currentAttributeOffset, charBuffer);
3247      int attributeLength = readInt(currentAttributeOffset + 2);
3248      currentAttributeOffset += 6;
3249      if (Constants.BOOTSTRAP_METHODS.equals(attributeName)) {
3250        // Read the num_bootstrap_methods field and create an array of this size.
3251        currentBootstrapMethodOffsets = new int[readUnsignedShort(currentAttributeOffset)];
3252        // Compute and store the offset of each 'bootstrap_methods' array field entry.
3253        int currentBootstrapMethodOffset = currentAttributeOffset + 2;
3254        for (int j = 0; j < currentBootstrapMethodOffsets.length; ++j) {
3255          currentBootstrapMethodOffsets[j] = currentBootstrapMethodOffset;
3256          // Skip the bootstrap_method_ref and num_bootstrap_arguments fields (2 bytes each),
3257          // as well as the bootstrap_arguments array field (of size num_bootstrap_arguments * 2).
3258          currentBootstrapMethodOffset +=
3259              4 + readUnsignedShort(currentBootstrapMethodOffset + 2) * 2;
3260        }
3261        return currentBootstrapMethodOffsets;
3262      }
3263      currentAttributeOffset += attributeLength;
3264    }
3265    throw new IllegalArgumentException();
3266  }
3267
3268  /**
3269   * Reads a non standard JVMS 'attribute' structure in {@link #classFileBuffer}.
3270   *
3271   * @param attributePrototypes prototypes of the attributes that must be parsed during the visit of
3272   *     the class. Any attribute whose type is not equal to the type of one the prototypes will not
3273   *     be parsed: its byte array value will be passed unchanged to the ClassWriter.
3274   * @param type the type of the attribute.
3275   * @param offset the start offset of the JVMS 'attribute' structure in {@link #classFileBuffer}.
3276   *     The 6 attribute header bytes (attribute_name_index and attribute_length) are not taken into
3277   *     account here.
3278   * @param length the length of the attribute's content (excluding the 6 attribute header bytes).
3279   * @param charBuffer the buffer to be used to read strings in the constant pool.
3280   * @param codeAttributeOffset the start offset of the enclosing Code attribute in {@link
3281   *     #classFileBuffer}, or -1 if the attribute to be read is not a code attribute. The 6
3282   *     attribute header bytes (attribute_name_index and attribute_length) are not taken into
3283   *     account here.
3284   * @param labels the labels of the method's code, or {@literal null} if the attribute to be read
3285   *     is not a code attribute.
3286   * @return the attribute that has been read.
3287   */
3288  private Attribute readAttribute(
3289      final Attribute[] attributePrototypes,
3290      final String type,
3291      final int offset,
3292      final int length,
3293      final char[] charBuffer,
3294      final int codeAttributeOffset,
3295      final Label[] labels) {
3296    for (Attribute attributePrototype : attributePrototypes) {
3297      if (attributePrototype.type.equals(type)) {
3298        return attributePrototype.read(
3299            this, offset, length, charBuffer, codeAttributeOffset, labels);
3300      }
3301    }
3302    return new Attribute(type).read(this, offset, length, null, -1, null);
3303  }
3304
3305  // -----------------------------------------------------------------------------------------------
3306  // Utility methods: low level parsing
3307  // -----------------------------------------------------------------------------------------------
3308
3309  /**
3310   * Returns the number of entries in the class's constant pool table.
3311   *
3312   * @return the number of entries in the class's constant pool table.
3313   */
3314  public int getItemCount() {
3315    return cpInfoOffsets.length;
3316  }
3317
3318  /**
3319   * Returns the start offset in this {@link ClassReader} of a JVMS 'cp_info' structure (i.e. a
3320   * constant pool entry), plus one. <i>This method is intended for {@link Attribute} sub classes,
3321   * and is normally not needed by class generators or adapters.</i>
3322   *
3323   * @param constantPoolEntryIndex the index a constant pool entry in the class's constant pool
3324   *     table.
3325   * @return the start offset in this {@link ClassReader} of the corresponding JVMS 'cp_info'
3326   *     structure, plus one.
3327   */
3328  public int getItem(final int constantPoolEntryIndex) {
3329    return cpInfoOffsets[constantPoolEntryIndex];
3330  }
3331
3332  /**
3333   * Returns a conservative estimate of the maximum length of the strings contained in the class's
3334   * constant pool table.
3335   *
3336   * @return a conservative estimate of the maximum length of the strings contained in the class's
3337   *     constant pool table.
3338   */
3339  public int getMaxStringLength() {
3340    return maxStringLength;
3341  }
3342
3343  /**
3344   * Reads a byte value in this {@link ClassReader}. <i>This method is intended for {@link
3345   * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3346   *
3347   * @param offset the start offset of the value to be read in this {@link ClassReader}.
3348   * @return the read value.
3349   */
3350  public int readByte(final int offset) {
3351    return classFileBuffer[offset] & 0xFF;
3352  }
3353
3354  /**
3355   * Reads an unsigned short value in this {@link ClassReader}. <i>This method is intended for
3356   * {@link Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3357   *
3358   * @param offset the start index of the value to be read in this {@link ClassReader}.
3359   * @return the read value.
3360   */
3361  public int readUnsignedShort(final int offset) {
3362    byte[] classBuffer = classFileBuffer;
3363    return ((classBuffer[offset] & 0xFF) << 8) | (classBuffer[offset + 1] & 0xFF);
3364  }
3365
3366  /**
3367   * Reads a signed short value in this {@link ClassReader}. <i>This method is intended for {@link
3368   * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3369   *
3370   * @param offset the start offset of the value to be read in this {@link ClassReader}.
3371   * @return the read value.
3372   */
3373  public short readShort(final int offset) {
3374    byte[] classBuffer = classFileBuffer;
3375    return (short) (((classBuffer[offset] & 0xFF) << 8) | (classBuffer[offset + 1] & 0xFF));
3376  }
3377
3378  /**
3379   * Reads a signed int value in this {@link ClassReader}. <i>This method is intended for {@link
3380   * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3381   *
3382   * @param offset the start offset of the value to be read in this {@link ClassReader}.
3383   * @return the read value.
3384   */
3385  public int readInt(final int offset) {
3386    byte[] classBuffer = classFileBuffer;
3387    return ((classBuffer[offset] & 0xFF) << 24)
3388        | ((classBuffer[offset + 1] & 0xFF) << 16)
3389        | ((classBuffer[offset + 2] & 0xFF) << 8)
3390        | (classBuffer[offset + 3] & 0xFF);
3391  }
3392
3393  /**
3394   * Reads a signed long value in this {@link ClassReader}. <i>This method is intended for {@link
3395   * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3396   *
3397   * @param offset the start offset of the value to be read in this {@link ClassReader}.
3398   * @return the read value.
3399   */
3400  public long readLong(final int offset) {
3401    long l1 = readInt(offset);
3402    long l0 = readInt(offset + 4) & 0xFFFFFFFFL;
3403    return (l1 << 32) | l0;
3404  }
3405
3406  /**
3407   * Reads a CONSTANT_Utf8 constant pool entry in this {@link ClassReader}. <i>This method is
3408   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3409   * adapters.</i>
3410   *
3411   * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3412   *     value is the index of a CONSTANT_Utf8 entry in the class's constant pool table.
3413   * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3414   *     large. It is not automatically resized.
3415   * @return the String corresponding to the specified CONSTANT_Utf8 entry.
3416   */
3417  // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
3418  public String readUTF8(final int offset, final char[] charBuffer) {
3419    int constantPoolEntryIndex = readUnsignedShort(offset);
3420    if (offset == 0 || constantPoolEntryIndex == 0) {
3421      return null;
3422    }
3423    return readUtf(constantPoolEntryIndex, charBuffer);
3424  }
3425
3426  /**
3427   * Reads a CONSTANT_Utf8 constant pool entry in {@link #classFileBuffer}.
3428   *
3429   * @param constantPoolEntryIndex the index of a CONSTANT_Utf8 entry in the class's constant pool
3430   *     table.
3431   * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3432   *     large. It is not automatically resized.
3433   * @return the String corresponding to the specified CONSTANT_Utf8 entry.
3434   */
3435  final String readUtf(final int constantPoolEntryIndex, final char[] charBuffer) {
3436    String value = constantUtf8Values[constantPoolEntryIndex];
3437    if (value != null) {
3438      return value;
3439    }
3440    int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3441    return constantUtf8Values[constantPoolEntryIndex] =
3442        readUtf(cpInfoOffset + 2, readUnsignedShort(cpInfoOffset), charBuffer);
3443  }
3444
3445  /**
3446   * Reads an UTF8 string in {@link #classFileBuffer}.
3447   *
3448   * @param utfOffset the start offset of the UTF8 string to be read.
3449   * @param utfLength the length of the UTF8 string to be read.
3450   * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3451   *     large. It is not automatically resized.
3452   * @return the String corresponding to the specified UTF8 string.
3453   */
3454  private String readUtf(final int utfOffset, final int utfLength, final char[] charBuffer) {
3455    int currentOffset = utfOffset;
3456    int endOffset = currentOffset + utfLength;
3457    int strLength = 0;
3458    byte[] classBuffer = classFileBuffer;
3459    while (currentOffset < endOffset) {
3460      int currentByte = classBuffer[currentOffset++];
3461      if ((currentByte & 0x80) == 0) {
3462        charBuffer[strLength++] = (char) (currentByte & 0x7F);
3463      } else if ((currentByte & 0xE0) == 0xC0) {
3464        charBuffer[strLength++] =
3465            (char) (((currentByte & 0x1F) << 6) + (classBuffer[currentOffset++] & 0x3F));
3466      } else {
3467        charBuffer[strLength++] =
3468            (char)
3469                (((currentByte & 0xF) << 12)
3470                    + ((classBuffer[currentOffset++] & 0x3F) << 6)
3471                    + (classBuffer[currentOffset++] & 0x3F));
3472      }
3473    }
3474    return new String(charBuffer, 0, strLength);
3475  }
3476
3477  /**
3478   * Reads a CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType, CONSTANT_Module or
3479   * CONSTANT_Package constant pool entry in {@link #classFileBuffer}. <i>This method is intended
3480   * for {@link Attribute} sub classes, and is normally not needed by class generators or
3481   * adapters.</i>
3482   *
3483   * @param offset the start offset of an unsigned short value in {@link #classFileBuffer}, whose
3484   *     value is the index of a CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType,
3485   *     CONSTANT_Module or CONSTANT_Package entry in class's constant pool table.
3486   * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3487   *     large. It is not automatically resized.
3488   * @return the String corresponding to the specified constant pool entry.
3489   */
3490  private String readStringish(final int offset, final char[] charBuffer) {
3491    // Get the start offset of the cp_info structure (plus one), and read the CONSTANT_Utf8 entry
3492    // designated by the first two bytes of this cp_info.
3493    return readUTF8(cpInfoOffsets[readUnsignedShort(offset)], charBuffer);
3494  }
3495
3496  /**
3497   * Reads a CONSTANT_Class constant pool entry in this {@link ClassReader}. <i>This method is
3498   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3499   * adapters.</i>
3500   *
3501   * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3502   *     value is the index of a CONSTANT_Class entry in class's constant pool table.
3503   * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3504   *     large. It is not automatically resized.
3505   * @return the String corresponding to the specified CONSTANT_Class entry.
3506   */
3507  public String readClass(final int offset, final char[] charBuffer) {
3508    return readStringish(offset, charBuffer);
3509  }
3510
3511  /**
3512   * Reads a CONSTANT_Module constant pool entry in this {@link ClassReader}. <i>This method is
3513   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3514   * adapters.</i>
3515   *
3516   * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3517   *     value is the index of a CONSTANT_Module entry in class's constant pool table.
3518   * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3519   *     large. It is not automatically resized.
3520   * @return the String corresponding to the specified CONSTANT_Module entry.
3521   */
3522  public String readModule(final int offset, final char[] charBuffer) {
3523    return readStringish(offset, charBuffer);
3524  }
3525
3526  /**
3527   * Reads a CONSTANT_Package constant pool entry in this {@link ClassReader}. <i>This method is
3528   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3529   * adapters.</i>
3530   *
3531   * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3532   *     value is the index of a CONSTANT_Package entry in class's constant pool table.
3533   * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3534   *     large. It is not automatically resized.
3535   * @return the String corresponding to the specified CONSTANT_Package entry.
3536   */
3537  public String readPackage(final int offset, final char[] charBuffer) {
3538    return readStringish(offset, charBuffer);
3539  }
3540
3541  /**
3542   * Reads a CONSTANT_Dynamic constant pool entry in {@link #classFileBuffer}.
3543   *
3544   * @param constantPoolEntryIndex the index of a CONSTANT_Dynamic entry in the class's constant
3545   *     pool table.
3546   * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3547   *     large. It is not automatically resized.
3548   * @return the ConstantDynamic corresponding to the specified CONSTANT_Dynamic entry.
3549   */
3550  private ConstantDynamic readConstantDynamic(
3551      final int constantPoolEntryIndex, final char[] charBuffer) {
3552    ConstantDynamic constantDynamic = constantDynamicValues[constantPoolEntryIndex];
3553    if (constantDynamic != null) {
3554      return constantDynamic;
3555    }
3556    int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3557    int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
3558    String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
3559    String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
3560    int bootstrapMethodOffset = bootstrapMethodOffsets[readUnsignedShort(cpInfoOffset)];
3561    Handle handle = (Handle) readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
3562    Object[] bootstrapMethodArguments = new Object[readUnsignedShort(bootstrapMethodOffset + 2)];
3563    bootstrapMethodOffset += 4;
3564    for (int i = 0; i < bootstrapMethodArguments.length; i++) {
3565      bootstrapMethodArguments[i] = readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
3566      bootstrapMethodOffset += 2;
3567    }
3568    return constantDynamicValues[constantPoolEntryIndex] =
3569        new ConstantDynamic(name, descriptor, handle, bootstrapMethodArguments);
3570  }
3571
3572  /**
3573   * Reads a numeric or string constant pool entry in this {@link ClassReader}. <i>This method is
3574   * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3575   * adapters.</i>
3576   *
3577   * @param constantPoolEntryIndex the index of a CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long,
3578   *     CONSTANT_Double, CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType,
3579   *     CONSTANT_MethodHandle or CONSTANT_Dynamic entry in the class's constant pool.
3580   * @param charBuffer the buffer to be used to read strings. This buffer must be sufficiently
3581   *     large. It is not automatically resized.
3582   * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String},
3583   *     {@link Type}, {@link Handle} or {@link ConstantDynamic} corresponding to the specified
3584   *     constant pool entry.
3585   */
3586  public Object readConst(final int constantPoolEntryIndex, final char[] charBuffer) {
3587    int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3588    switch (classFileBuffer[cpInfoOffset - 1]) {
3589      case Symbol.CONSTANT_INTEGER_TAG:
3590        return readInt(cpInfoOffset);
3591      case Symbol.CONSTANT_FLOAT_TAG:
3592        return Float.intBitsToFloat(readInt(cpInfoOffset));
3593      case Symbol.CONSTANT_LONG_TAG:
3594        return readLong(cpInfoOffset);
3595      case Symbol.CONSTANT_DOUBLE_TAG:
3596        return Double.longBitsToDouble(readLong(cpInfoOffset));
3597      case Symbol.CONSTANT_CLASS_TAG:
3598        return Type.getObjectType(readUTF8(cpInfoOffset, charBuffer));
3599      case Symbol.CONSTANT_STRING_TAG:
3600        return readUTF8(cpInfoOffset, charBuffer);
3601      case Symbol.CONSTANT_METHOD_TYPE_TAG:
3602        return Type.getMethodType(readUTF8(cpInfoOffset, charBuffer));
3603      case Symbol.CONSTANT_METHOD_HANDLE_TAG:
3604        int referenceKind = readByte(cpInfoOffset);
3605        int referenceCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 1)];
3606        int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(referenceCpInfoOffset + 2)];
3607        String owner = readClass(referenceCpInfoOffset, charBuffer);
3608        String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
3609        String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
3610        boolean isInterface =
3611            classFileBuffer[referenceCpInfoOffset - 1] == Symbol.CONSTANT_INTERFACE_METHODREF_TAG;
3612        return new Handle(referenceKind, owner, name, descriptor, isInterface);
3613      case Symbol.CONSTANT_DYNAMIC_TAG:
3614        return readConstantDynamic(constantPoolEntryIndex, charBuffer);
3615      default:
3616        throw new IllegalArgumentException();
3617    }
3618  }
3619}