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