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