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