• 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.V21) {
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       readBytecodeInstructionOffset(currentBytecodeOffset);
2054 
2055       // Visit the label and the line number(s) for this bytecode offset, if any.
2056       Label currentLabel = labels[currentBytecodeOffset];
2057       if (currentLabel != null) {
2058         currentLabel.accept(methodVisitor, (context.parsingOptions & SKIP_DEBUG) == 0);
2059       }
2060 
2061       // Visit the stack map frame for this bytecode offset, if any.
2062       while (stackMapFrameOffset != 0
2063           && (context.currentFrameOffset == currentBytecodeOffset
2064               || context.currentFrameOffset == -1)) {
2065         // If there is a stack map frame for this offset, make methodVisitor visit it, and read the
2066         // next stack map frame if there is one.
2067         if (context.currentFrameOffset != -1) {
2068           if (!compressedFrames || expandFrames) {
2069             methodVisitor.visitFrame(
2070                 Opcodes.F_NEW,
2071                 context.currentFrameLocalCount,
2072                 context.currentFrameLocalTypes,
2073                 context.currentFrameStackCount,
2074                 context.currentFrameStackTypes);
2075           } else {
2076             methodVisitor.visitFrame(
2077                 context.currentFrameType,
2078                 context.currentFrameLocalCountDelta,
2079                 context.currentFrameLocalTypes,
2080                 context.currentFrameStackCount,
2081                 context.currentFrameStackTypes);
2082           }
2083           // Since there is already a stack map frame for this bytecode offset, there is no need to
2084           // insert a new one.
2085           insertFrame = false;
2086         }
2087         if (stackMapFrameOffset < stackMapTableEndOffset) {
2088           stackMapFrameOffset =
2089               readStackMapFrame(stackMapFrameOffset, compressedFrames, expandFrames, context);
2090         } else {
2091           stackMapFrameOffset = 0;
2092         }
2093       }
2094 
2095       // Insert a stack map frame for this bytecode offset, if requested by setting insertFrame to
2096       // true during the previous iteration. The actual frame content is computed in MethodWriter.
2097       if (insertFrame) {
2098         if ((context.parsingOptions & EXPAND_FRAMES) != 0) {
2099           methodVisitor.visitFrame(Constants.F_INSERT, 0, null, 0, null);
2100         }
2101         insertFrame = false;
2102       }
2103 
2104       // Visit the instruction at this bytecode offset.
2105       int opcode = classBuffer[currentOffset] & 0xFF;
2106       switch (opcode) {
2107         case Opcodes.NOP:
2108         case Opcodes.ACONST_NULL:
2109         case Opcodes.ICONST_M1:
2110         case Opcodes.ICONST_0:
2111         case Opcodes.ICONST_1:
2112         case Opcodes.ICONST_2:
2113         case Opcodes.ICONST_3:
2114         case Opcodes.ICONST_4:
2115         case Opcodes.ICONST_5:
2116         case Opcodes.LCONST_0:
2117         case Opcodes.LCONST_1:
2118         case Opcodes.FCONST_0:
2119         case Opcodes.FCONST_1:
2120         case Opcodes.FCONST_2:
2121         case Opcodes.DCONST_0:
2122         case Opcodes.DCONST_1:
2123         case Opcodes.IALOAD:
2124         case Opcodes.LALOAD:
2125         case Opcodes.FALOAD:
2126         case Opcodes.DALOAD:
2127         case Opcodes.AALOAD:
2128         case Opcodes.BALOAD:
2129         case Opcodes.CALOAD:
2130         case Opcodes.SALOAD:
2131         case Opcodes.IASTORE:
2132         case Opcodes.LASTORE:
2133         case Opcodes.FASTORE:
2134         case Opcodes.DASTORE:
2135         case Opcodes.AASTORE:
2136         case Opcodes.BASTORE:
2137         case Opcodes.CASTORE:
2138         case Opcodes.SASTORE:
2139         case Opcodes.POP:
2140         case Opcodes.POP2:
2141         case Opcodes.DUP:
2142         case Opcodes.DUP_X1:
2143         case Opcodes.DUP_X2:
2144         case Opcodes.DUP2:
2145         case Opcodes.DUP2_X1:
2146         case Opcodes.DUP2_X2:
2147         case Opcodes.SWAP:
2148         case Opcodes.IADD:
2149         case Opcodes.LADD:
2150         case Opcodes.FADD:
2151         case Opcodes.DADD:
2152         case Opcodes.ISUB:
2153         case Opcodes.LSUB:
2154         case Opcodes.FSUB:
2155         case Opcodes.DSUB:
2156         case Opcodes.IMUL:
2157         case Opcodes.LMUL:
2158         case Opcodes.FMUL:
2159         case Opcodes.DMUL:
2160         case Opcodes.IDIV:
2161         case Opcodes.LDIV:
2162         case Opcodes.FDIV:
2163         case Opcodes.DDIV:
2164         case Opcodes.IREM:
2165         case Opcodes.LREM:
2166         case Opcodes.FREM:
2167         case Opcodes.DREM:
2168         case Opcodes.INEG:
2169         case Opcodes.LNEG:
2170         case Opcodes.FNEG:
2171         case Opcodes.DNEG:
2172         case Opcodes.ISHL:
2173         case Opcodes.LSHL:
2174         case Opcodes.ISHR:
2175         case Opcodes.LSHR:
2176         case Opcodes.IUSHR:
2177         case Opcodes.LUSHR:
2178         case Opcodes.IAND:
2179         case Opcodes.LAND:
2180         case Opcodes.IOR:
2181         case Opcodes.LOR:
2182         case Opcodes.IXOR:
2183         case Opcodes.LXOR:
2184         case Opcodes.I2L:
2185         case Opcodes.I2F:
2186         case Opcodes.I2D:
2187         case Opcodes.L2I:
2188         case Opcodes.L2F:
2189         case Opcodes.L2D:
2190         case Opcodes.F2I:
2191         case Opcodes.F2L:
2192         case Opcodes.F2D:
2193         case Opcodes.D2I:
2194         case Opcodes.D2L:
2195         case Opcodes.D2F:
2196         case Opcodes.I2B:
2197         case Opcodes.I2C:
2198         case Opcodes.I2S:
2199         case Opcodes.LCMP:
2200         case Opcodes.FCMPL:
2201         case Opcodes.FCMPG:
2202         case Opcodes.DCMPL:
2203         case Opcodes.DCMPG:
2204         case Opcodes.IRETURN:
2205         case Opcodes.LRETURN:
2206         case Opcodes.FRETURN:
2207         case Opcodes.DRETURN:
2208         case Opcodes.ARETURN:
2209         case Opcodes.RETURN:
2210         case Opcodes.ARRAYLENGTH:
2211         case Opcodes.ATHROW:
2212         case Opcodes.MONITORENTER:
2213         case Opcodes.MONITOREXIT:
2214           methodVisitor.visitInsn(opcode);
2215           currentOffset += 1;
2216           break;
2217         case Constants.ILOAD_0:
2218         case Constants.ILOAD_1:
2219         case Constants.ILOAD_2:
2220         case Constants.ILOAD_3:
2221         case Constants.LLOAD_0:
2222         case Constants.LLOAD_1:
2223         case Constants.LLOAD_2:
2224         case Constants.LLOAD_3:
2225         case Constants.FLOAD_0:
2226         case Constants.FLOAD_1:
2227         case Constants.FLOAD_2:
2228         case Constants.FLOAD_3:
2229         case Constants.DLOAD_0:
2230         case Constants.DLOAD_1:
2231         case Constants.DLOAD_2:
2232         case Constants.DLOAD_3:
2233         case Constants.ALOAD_0:
2234         case Constants.ALOAD_1:
2235         case Constants.ALOAD_2:
2236         case Constants.ALOAD_3:
2237           opcode -= Constants.ILOAD_0;
2238           methodVisitor.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
2239           currentOffset += 1;
2240           break;
2241         case Constants.ISTORE_0:
2242         case Constants.ISTORE_1:
2243         case Constants.ISTORE_2:
2244         case Constants.ISTORE_3:
2245         case Constants.LSTORE_0:
2246         case Constants.LSTORE_1:
2247         case Constants.LSTORE_2:
2248         case Constants.LSTORE_3:
2249         case Constants.FSTORE_0:
2250         case Constants.FSTORE_1:
2251         case Constants.FSTORE_2:
2252         case Constants.FSTORE_3:
2253         case Constants.DSTORE_0:
2254         case Constants.DSTORE_1:
2255         case Constants.DSTORE_2:
2256         case Constants.DSTORE_3:
2257         case Constants.ASTORE_0:
2258         case Constants.ASTORE_1:
2259         case Constants.ASTORE_2:
2260         case Constants.ASTORE_3:
2261           opcode -= Constants.ISTORE_0;
2262           methodVisitor.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), opcode & 0x3);
2263           currentOffset += 1;
2264           break;
2265         case Opcodes.IFEQ:
2266         case Opcodes.IFNE:
2267         case Opcodes.IFLT:
2268         case Opcodes.IFGE:
2269         case Opcodes.IFGT:
2270         case Opcodes.IFLE:
2271         case Opcodes.IF_ICMPEQ:
2272         case Opcodes.IF_ICMPNE:
2273         case Opcodes.IF_ICMPLT:
2274         case Opcodes.IF_ICMPGE:
2275         case Opcodes.IF_ICMPGT:
2276         case Opcodes.IF_ICMPLE:
2277         case Opcodes.IF_ACMPEQ:
2278         case Opcodes.IF_ACMPNE:
2279         case Opcodes.GOTO:
2280         case Opcodes.JSR:
2281         case Opcodes.IFNULL:
2282         case Opcodes.IFNONNULL:
2283           methodVisitor.visitJumpInsn(
2284               opcode, labels[currentBytecodeOffset + readShort(currentOffset + 1)]);
2285           currentOffset += 3;
2286           break;
2287         case Constants.GOTO_W:
2288         case Constants.JSR_W:
2289           methodVisitor.visitJumpInsn(
2290               opcode - wideJumpOpcodeDelta,
2291               labels[currentBytecodeOffset + readInt(currentOffset + 1)]);
2292           currentOffset += 5;
2293           break;
2294         case Constants.ASM_IFEQ:
2295         case Constants.ASM_IFNE:
2296         case Constants.ASM_IFLT:
2297         case Constants.ASM_IFGE:
2298         case Constants.ASM_IFGT:
2299         case Constants.ASM_IFLE:
2300         case Constants.ASM_IF_ICMPEQ:
2301         case Constants.ASM_IF_ICMPNE:
2302         case Constants.ASM_IF_ICMPLT:
2303         case Constants.ASM_IF_ICMPGE:
2304         case Constants.ASM_IF_ICMPGT:
2305         case Constants.ASM_IF_ICMPLE:
2306         case Constants.ASM_IF_ACMPEQ:
2307         case Constants.ASM_IF_ACMPNE:
2308         case Constants.ASM_GOTO:
2309         case Constants.ASM_JSR:
2310         case Constants.ASM_IFNULL:
2311         case Constants.ASM_IFNONNULL:
2312           {
2313             // A forward jump with an offset > 32767. In this case we automatically replace ASM_GOTO
2314             // with GOTO_W, ASM_JSR with JSR_W and ASM_IFxxx <l> with IFNOTxxx <L> GOTO_W <l> L:...,
2315             // where IFNOTxxx is the "opposite" opcode of ASMS_IFxxx (e.g. IFNE for ASM_IFEQ) and
2316             // where <L> designates the instruction just after the GOTO_W.
2317             // First, change the ASM specific opcodes ASM_IFEQ ... ASM_JSR, ASM_IFNULL and
2318             // ASM_IFNONNULL to IFEQ ... JSR, IFNULL and IFNONNULL.
2319             opcode =
2320                 opcode < Constants.ASM_IFNULL
2321                     ? opcode - Constants.ASM_OPCODE_DELTA
2322                     : opcode - Constants.ASM_IFNULL_OPCODE_DELTA;
2323             Label target = labels[currentBytecodeOffset + readUnsignedShort(currentOffset + 1)];
2324             if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
2325               // Replace GOTO with GOTO_W and JSR with JSR_W.
2326               methodVisitor.visitJumpInsn(opcode + Constants.WIDE_JUMP_OPCODE_DELTA, target);
2327             } else {
2328               // Compute the "opposite" of opcode. This can be done by flipping the least
2329               // significant bit for IFNULL and IFNONNULL, and similarly for IFEQ ... IF_ACMPEQ
2330               // (with a pre and post offset by 1).
2331               opcode = opcode < Opcodes.GOTO ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1;
2332               Label endif = createLabel(currentBytecodeOffset + 3, labels);
2333               methodVisitor.visitJumpInsn(opcode, endif);
2334               methodVisitor.visitJumpInsn(Constants.GOTO_W, target);
2335               // endif designates the instruction just after GOTO_W, and is visited as part of the
2336               // next instruction. Since it is a jump target, we need to insert a frame here.
2337               insertFrame = true;
2338             }
2339             currentOffset += 3;
2340             break;
2341           }
2342         case Constants.ASM_GOTO_W:
2343           // Replace ASM_GOTO_W with GOTO_W.
2344           methodVisitor.visitJumpInsn(
2345               Constants.GOTO_W, labels[currentBytecodeOffset + readInt(currentOffset + 1)]);
2346           // The instruction just after is a jump target (because ASM_GOTO_W is used in patterns
2347           // IFNOTxxx <L> ASM_GOTO_W <l> L:..., see MethodWriter), so we need to insert a frame
2348           // here.
2349           insertFrame = true;
2350           currentOffset += 5;
2351           break;
2352         case Constants.WIDE:
2353           opcode = classBuffer[currentOffset + 1] & 0xFF;
2354           if (opcode == Opcodes.IINC) {
2355             methodVisitor.visitIincInsn(
2356                 readUnsignedShort(currentOffset + 2), readShort(currentOffset + 4));
2357             currentOffset += 6;
2358           } else {
2359             methodVisitor.visitVarInsn(opcode, readUnsignedShort(currentOffset + 2));
2360             currentOffset += 4;
2361           }
2362           break;
2363         case Opcodes.TABLESWITCH:
2364           {
2365             // Skip 0 to 3 padding bytes.
2366             currentOffset += 4 - (currentBytecodeOffset & 3);
2367             // Read the instruction.
2368             Label defaultLabel = labels[currentBytecodeOffset + readInt(currentOffset)];
2369             int low = readInt(currentOffset + 4);
2370             int high = readInt(currentOffset + 8);
2371             currentOffset += 12;
2372             Label[] table = new Label[high - low + 1];
2373             for (int i = 0; i < table.length; ++i) {
2374               table[i] = labels[currentBytecodeOffset + readInt(currentOffset)];
2375               currentOffset += 4;
2376             }
2377             methodVisitor.visitTableSwitchInsn(low, high, defaultLabel, table);
2378             break;
2379           }
2380         case Opcodes.LOOKUPSWITCH:
2381           {
2382             // Skip 0 to 3 padding bytes.
2383             currentOffset += 4 - (currentBytecodeOffset & 3);
2384             // Read the instruction.
2385             Label defaultLabel = labels[currentBytecodeOffset + readInt(currentOffset)];
2386             int numPairs = readInt(currentOffset + 4);
2387             currentOffset += 8;
2388             int[] keys = new int[numPairs];
2389             Label[] values = new Label[numPairs];
2390             for (int i = 0; i < numPairs; ++i) {
2391               keys[i] = readInt(currentOffset);
2392               values[i] = labels[currentBytecodeOffset + readInt(currentOffset + 4)];
2393               currentOffset += 8;
2394             }
2395             methodVisitor.visitLookupSwitchInsn(defaultLabel, keys, values);
2396             break;
2397           }
2398         case Opcodes.ILOAD:
2399         case Opcodes.LLOAD:
2400         case Opcodes.FLOAD:
2401         case Opcodes.DLOAD:
2402         case Opcodes.ALOAD:
2403         case Opcodes.ISTORE:
2404         case Opcodes.LSTORE:
2405         case Opcodes.FSTORE:
2406         case Opcodes.DSTORE:
2407         case Opcodes.ASTORE:
2408         case Opcodes.RET:
2409           methodVisitor.visitVarInsn(opcode, classBuffer[currentOffset + 1] & 0xFF);
2410           currentOffset += 2;
2411           break;
2412         case Opcodes.BIPUSH:
2413         case Opcodes.NEWARRAY:
2414           methodVisitor.visitIntInsn(opcode, classBuffer[currentOffset + 1]);
2415           currentOffset += 2;
2416           break;
2417         case Opcodes.SIPUSH:
2418           methodVisitor.visitIntInsn(opcode, readShort(currentOffset + 1));
2419           currentOffset += 3;
2420           break;
2421         case Opcodes.LDC:
2422           methodVisitor.visitLdcInsn(readConst(classBuffer[currentOffset + 1] & 0xFF, charBuffer));
2423           currentOffset += 2;
2424           break;
2425         case Constants.LDC_W:
2426         case Constants.LDC2_W:
2427           methodVisitor.visitLdcInsn(readConst(readUnsignedShort(currentOffset + 1), charBuffer));
2428           currentOffset += 3;
2429           break;
2430         case Opcodes.GETSTATIC:
2431         case Opcodes.PUTSTATIC:
2432         case Opcodes.GETFIELD:
2433         case Opcodes.PUTFIELD:
2434         case Opcodes.INVOKEVIRTUAL:
2435         case Opcodes.INVOKESPECIAL:
2436         case Opcodes.INVOKESTATIC:
2437         case Opcodes.INVOKEINTERFACE:
2438           {
2439             int cpInfoOffset = cpInfoOffsets[readUnsignedShort(currentOffset + 1)];
2440             int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
2441             String owner = readClass(cpInfoOffset, charBuffer);
2442             String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
2443             String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
2444             if (opcode < Opcodes.INVOKEVIRTUAL) {
2445               methodVisitor.visitFieldInsn(opcode, owner, name, descriptor);
2446             } else {
2447               boolean isInterface =
2448                   classBuffer[cpInfoOffset - 1] == Symbol.CONSTANT_INTERFACE_METHODREF_TAG;
2449               methodVisitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
2450             }
2451             if (opcode == Opcodes.INVOKEINTERFACE) {
2452               currentOffset += 5;
2453             } else {
2454               currentOffset += 3;
2455             }
2456             break;
2457           }
2458         case Opcodes.INVOKEDYNAMIC:
2459           {
2460             int cpInfoOffset = cpInfoOffsets[readUnsignedShort(currentOffset + 1)];
2461             int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
2462             String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
2463             String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
2464             int bootstrapMethodOffset = bootstrapMethodOffsets[readUnsignedShort(cpInfoOffset)];
2465             Handle handle =
2466                 (Handle) readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
2467             Object[] bootstrapMethodArguments =
2468                 new Object[readUnsignedShort(bootstrapMethodOffset + 2)];
2469             bootstrapMethodOffset += 4;
2470             for (int i = 0; i < bootstrapMethodArguments.length; i++) {
2471               bootstrapMethodArguments[i] =
2472                   readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
2473               bootstrapMethodOffset += 2;
2474             }
2475             methodVisitor.visitInvokeDynamicInsn(
2476                 name, descriptor, handle, bootstrapMethodArguments);
2477             currentOffset += 5;
2478             break;
2479           }
2480         case Opcodes.NEW:
2481         case Opcodes.ANEWARRAY:
2482         case Opcodes.CHECKCAST:
2483         case Opcodes.INSTANCEOF:
2484           methodVisitor.visitTypeInsn(opcode, readClass(currentOffset + 1, charBuffer));
2485           currentOffset += 3;
2486           break;
2487         case Opcodes.IINC:
2488           methodVisitor.visitIincInsn(
2489               classBuffer[currentOffset + 1] & 0xFF, classBuffer[currentOffset + 2]);
2490           currentOffset += 3;
2491           break;
2492         case Opcodes.MULTIANEWARRAY:
2493           methodVisitor.visitMultiANewArrayInsn(
2494               readClass(currentOffset + 1, charBuffer), classBuffer[currentOffset + 3] & 0xFF);
2495           currentOffset += 4;
2496           break;
2497         default:
2498           throw new AssertionError();
2499       }
2500 
2501       // Visit the runtime visible instruction annotations, if any.
2502       while (visibleTypeAnnotationOffsets != null
2503           && currentVisibleTypeAnnotationIndex < visibleTypeAnnotationOffsets.length
2504           && currentVisibleTypeAnnotationBytecodeOffset <= currentBytecodeOffset) {
2505         if (currentVisibleTypeAnnotationBytecodeOffset == currentBytecodeOffset) {
2506           // Parse the target_type, target_info and target_path fields.
2507           int currentAnnotationOffset =
2508               readTypeAnnotationTarget(
2509                   context, visibleTypeAnnotationOffsets[currentVisibleTypeAnnotationIndex]);
2510           // Parse the type_index field.
2511           String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
2512           currentAnnotationOffset += 2;
2513           // Parse num_element_value_pairs and element_value_pairs and visit these values.
2514           readElementValues(
2515               methodVisitor.visitInsnAnnotation(
2516                   context.currentTypeAnnotationTarget,
2517                   context.currentTypeAnnotationTargetPath,
2518                   annotationDescriptor,
2519                   /* visible = */ true),
2520               currentAnnotationOffset,
2521               /* named = */ true,
2522               charBuffer);
2523         }
2524         currentVisibleTypeAnnotationBytecodeOffset =
2525             getTypeAnnotationBytecodeOffset(
2526                 visibleTypeAnnotationOffsets, ++currentVisibleTypeAnnotationIndex);
2527       }
2528 
2529       // Visit the runtime invisible instruction annotations, if any.
2530       while (invisibleTypeAnnotationOffsets != null
2531           && currentInvisibleTypeAnnotationIndex < invisibleTypeAnnotationOffsets.length
2532           && currentInvisibleTypeAnnotationBytecodeOffset <= currentBytecodeOffset) {
2533         if (currentInvisibleTypeAnnotationBytecodeOffset == currentBytecodeOffset) {
2534           // Parse the target_type, target_info and target_path fields.
2535           int currentAnnotationOffset =
2536               readTypeAnnotationTarget(
2537                   context, invisibleTypeAnnotationOffsets[currentInvisibleTypeAnnotationIndex]);
2538           // Parse the type_index field.
2539           String annotationDescriptor = readUTF8(currentAnnotationOffset, charBuffer);
2540           currentAnnotationOffset += 2;
2541           // Parse num_element_value_pairs and element_value_pairs and visit these values.
2542           readElementValues(
2543               methodVisitor.visitInsnAnnotation(
2544                   context.currentTypeAnnotationTarget,
2545                   context.currentTypeAnnotationTargetPath,
2546                   annotationDescriptor,
2547                   /* visible = */ false),
2548               currentAnnotationOffset,
2549               /* named = */ true,
2550               charBuffer);
2551         }
2552         currentInvisibleTypeAnnotationBytecodeOffset =
2553             getTypeAnnotationBytecodeOffset(
2554                 invisibleTypeAnnotationOffsets, ++currentInvisibleTypeAnnotationIndex);
2555       }
2556     }
2557     if (labels[codeLength] != null) {
2558       methodVisitor.visitLabel(labels[codeLength]);
2559     }
2560 
2561     // Visit LocalVariableTable and LocalVariableTypeTable attributes.
2562     if (localVariableTableOffset != 0 && (context.parsingOptions & SKIP_DEBUG) == 0) {
2563       // The (start_pc, index, signature_index) fields of each entry of the LocalVariableTypeTable.
2564       int[] typeTable = null;
2565       if (localVariableTypeTableOffset != 0) {
2566         typeTable = new int[readUnsignedShort(localVariableTypeTableOffset) * 3];
2567         currentOffset = localVariableTypeTableOffset + 2;
2568         int typeTableIndex = typeTable.length;
2569         while (typeTableIndex > 0) {
2570           // Store the offset of 'signature_index', and the value of 'index' and 'start_pc'.
2571           typeTable[--typeTableIndex] = currentOffset + 6;
2572           typeTable[--typeTableIndex] = readUnsignedShort(currentOffset + 8);
2573           typeTable[--typeTableIndex] = readUnsignedShort(currentOffset);
2574           currentOffset += 10;
2575         }
2576       }
2577       int localVariableTableLength = readUnsignedShort(localVariableTableOffset);
2578       currentOffset = localVariableTableOffset + 2;
2579       while (localVariableTableLength-- > 0) {
2580         int startPc = readUnsignedShort(currentOffset);
2581         int length = readUnsignedShort(currentOffset + 2);
2582         String name = readUTF8(currentOffset + 4, charBuffer);
2583         String descriptor = readUTF8(currentOffset + 6, charBuffer);
2584         int index = readUnsignedShort(currentOffset + 8);
2585         currentOffset += 10;
2586         String signature = null;
2587         if (typeTable != null) {
2588           for (int i = 0; i < typeTable.length; i += 3) {
2589             if (typeTable[i] == startPc && typeTable[i + 1] == index) {
2590               signature = readUTF8(typeTable[i + 2], charBuffer);
2591               break;
2592             }
2593           }
2594         }
2595         methodVisitor.visitLocalVariable(
2596             name, descriptor, signature, labels[startPc], labels[startPc + length], index);
2597       }
2598     }
2599 
2600     // Visit the local variable type annotations of the RuntimeVisibleTypeAnnotations attribute.
2601     if (visibleTypeAnnotationOffsets != null) {
2602       for (int typeAnnotationOffset : visibleTypeAnnotationOffsets) {
2603         int targetType = readByte(typeAnnotationOffset);
2604         if (targetType == TypeReference.LOCAL_VARIABLE
2605             || targetType == TypeReference.RESOURCE_VARIABLE) {
2606           // Parse the target_type, target_info and target_path fields.
2607           currentOffset = readTypeAnnotationTarget(context, typeAnnotationOffset);
2608           // Parse the type_index field.
2609           String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2610           currentOffset += 2;
2611           // Parse num_element_value_pairs and element_value_pairs and visit these values.
2612           readElementValues(
2613               methodVisitor.visitLocalVariableAnnotation(
2614                   context.currentTypeAnnotationTarget,
2615                   context.currentTypeAnnotationTargetPath,
2616                   context.currentLocalVariableAnnotationRangeStarts,
2617                   context.currentLocalVariableAnnotationRangeEnds,
2618                   context.currentLocalVariableAnnotationRangeIndices,
2619                   annotationDescriptor,
2620                   /* visible = */ true),
2621               currentOffset,
2622               /* named = */ true,
2623               charBuffer);
2624         }
2625       }
2626     }
2627 
2628     // Visit the local variable type annotations of the RuntimeInvisibleTypeAnnotations attribute.
2629     if (invisibleTypeAnnotationOffsets != null) {
2630       for (int typeAnnotationOffset : invisibleTypeAnnotationOffsets) {
2631         int targetType = readByte(typeAnnotationOffset);
2632         if (targetType == TypeReference.LOCAL_VARIABLE
2633             || targetType == TypeReference.RESOURCE_VARIABLE) {
2634           // Parse the target_type, target_info and target_path fields.
2635           currentOffset = readTypeAnnotationTarget(context, typeAnnotationOffset);
2636           // Parse the type_index field.
2637           String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2638           currentOffset += 2;
2639           // Parse num_element_value_pairs and element_value_pairs and visit these values.
2640           readElementValues(
2641               methodVisitor.visitLocalVariableAnnotation(
2642                   context.currentTypeAnnotationTarget,
2643                   context.currentTypeAnnotationTargetPath,
2644                   context.currentLocalVariableAnnotationRangeStarts,
2645                   context.currentLocalVariableAnnotationRangeEnds,
2646                   context.currentLocalVariableAnnotationRangeIndices,
2647                   annotationDescriptor,
2648                   /* visible = */ false),
2649               currentOffset,
2650               /* named = */ true,
2651               charBuffer);
2652         }
2653       }
2654     }
2655 
2656     // Visit the non standard attributes.
2657     while (attributes != null) {
2658       // Copy and reset the nextAttribute field so that it can also be used in MethodWriter.
2659       Attribute nextAttribute = attributes.nextAttribute;
2660       attributes.nextAttribute = null;
2661       methodVisitor.visitAttribute(attributes);
2662       attributes = nextAttribute;
2663     }
2664 
2665     // Visit the max stack and max locals values.
2666     methodVisitor.visitMaxs(maxStack, maxLocals);
2667   }
2668 
2669   /**
2670    * Handles the bytecode offset of the next instruction to be visited in {@link
2671    * #accept(ClassVisitor,int)}. This method is called just before the instruction and before its
2672    * associated label and stack map frame, if any. The default implementation of this method does
2673    * nothing. Subclasses can override this method to store the argument in a mutable field, for
2674    * instance, so that {@link MethodVisitor} instances can get the bytecode offset of each visited
2675    * instruction (if so, the usual concurrency issues related to mutable data should be addressed).
2676    *
2677    * @param bytecodeOffset the bytecode offset of the next instruction to be visited.
2678    */
2679   protected void readBytecodeInstructionOffset(final int bytecodeOffset) {
2680     // Do nothing by default.
2681   }
2682 
2683   /**
2684    * Returns the label corresponding to the given bytecode offset. The default implementation of
2685    * this method creates a label for the given offset if it has not been already created.
2686    *
2687    * @param bytecodeOffset a bytecode offset in a method.
2688    * @param labels the already created labels, indexed by their offset. If a label already exists
2689    *     for bytecodeOffset this method must not create a new one. Otherwise it must store the new
2690    *     label in this array.
2691    * @return a non null Label, which must be equal to labels[bytecodeOffset].
2692    */
2693   protected Label readLabel(final int bytecodeOffset, final Label[] labels) {
2694     if (labels[bytecodeOffset] == null) {
2695       labels[bytecodeOffset] = new Label();
2696     }
2697     return labels[bytecodeOffset];
2698   }
2699 
2700   /**
2701    * Creates a label without the {@link Label#FLAG_DEBUG_ONLY} flag set, for the given bytecode
2702    * offset. The label is created with a call to {@link #readLabel} and its {@link
2703    * Label#FLAG_DEBUG_ONLY} flag is cleared.
2704    *
2705    * @param bytecodeOffset a bytecode offset in a method.
2706    * @param labels the already created labels, indexed by their offset.
2707    * @return a Label without the {@link Label#FLAG_DEBUG_ONLY} flag set.
2708    */
2709   private Label createLabel(final int bytecodeOffset, final Label[] labels) {
2710     Label label = readLabel(bytecodeOffset, labels);
2711     label.flags &= ~Label.FLAG_DEBUG_ONLY;
2712     return label;
2713   }
2714 
2715   /**
2716    * Creates a label with the {@link Label#FLAG_DEBUG_ONLY} flag set, if there is no already
2717    * existing label for the given bytecode offset (otherwise does nothing). The label is created
2718    * with a call to {@link #readLabel}.
2719    *
2720    * @param bytecodeOffset a bytecode offset in a method.
2721    * @param labels the already created labels, indexed by their offset.
2722    */
2723   private void createDebugLabel(final int bytecodeOffset, final Label[] labels) {
2724     if (labels[bytecodeOffset] == null) {
2725       readLabel(bytecodeOffset, labels).flags |= Label.FLAG_DEBUG_ONLY;
2726     }
2727   }
2728 
2729   // ----------------------------------------------------------------------------------------------
2730   // Methods to parse annotations, type annotations and parameter annotations
2731   // ----------------------------------------------------------------------------------------------
2732 
2733   /**
2734    * Parses a Runtime[In]VisibleTypeAnnotations attribute to find the offset of each type_annotation
2735    * entry it contains, to find the corresponding labels, and to visit the try catch block
2736    * annotations.
2737    *
2738    * @param methodVisitor the method visitor to be used to visit the try catch block annotations.
2739    * @param context information about the class being parsed.
2740    * @param runtimeTypeAnnotationsOffset the start offset of a Runtime[In]VisibleTypeAnnotations
2741    *     attribute, excluding the attribute_info's attribute_name_index and attribute_length fields.
2742    * @param visible true if the attribute to parse is a RuntimeVisibleTypeAnnotations attribute,
2743    *     false it is a RuntimeInvisibleTypeAnnotations attribute.
2744    * @return the start offset of each entry of the Runtime[In]VisibleTypeAnnotations_attribute's
2745    *     'annotations' array field.
2746    */
2747   private int[] readTypeAnnotations(
2748       final MethodVisitor methodVisitor,
2749       final Context context,
2750       final int runtimeTypeAnnotationsOffset,
2751       final boolean visible) {
2752     char[] charBuffer = context.charBuffer;
2753     int currentOffset = runtimeTypeAnnotationsOffset;
2754     // Read the num_annotations field and create an array to store the type_annotation offsets.
2755     int[] typeAnnotationsOffsets = new int[readUnsignedShort(currentOffset)];
2756     currentOffset += 2;
2757     // Parse the 'annotations' array field.
2758     for (int i = 0; i < typeAnnotationsOffsets.length; ++i) {
2759       typeAnnotationsOffsets[i] = currentOffset;
2760       // Parse the type_annotation's target_type and the target_info fields. The size of the
2761       // target_info field depends on the value of target_type.
2762       int targetType = readInt(currentOffset);
2763       switch (targetType >>> 24) {
2764         case TypeReference.LOCAL_VARIABLE:
2765         case TypeReference.RESOURCE_VARIABLE:
2766           // A localvar_target has a variable size, which depends on the value of their table_length
2767           // field. It also references bytecode offsets, for which we need labels.
2768           int tableLength = readUnsignedShort(currentOffset + 1);
2769           currentOffset += 3;
2770           while (tableLength-- > 0) {
2771             int startPc = readUnsignedShort(currentOffset);
2772             int length = readUnsignedShort(currentOffset + 2);
2773             // Skip the index field (2 bytes).
2774             currentOffset += 6;
2775             createLabel(startPc, context.currentMethodLabels);
2776             createLabel(startPc + length, context.currentMethodLabels);
2777           }
2778           break;
2779         case TypeReference.CAST:
2780         case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
2781         case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
2782         case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
2783         case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
2784           currentOffset += 4;
2785           break;
2786         case TypeReference.CLASS_EXTENDS:
2787         case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
2788         case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
2789         case TypeReference.THROWS:
2790         case TypeReference.EXCEPTION_PARAMETER:
2791         case TypeReference.INSTANCEOF:
2792         case TypeReference.NEW:
2793         case TypeReference.CONSTRUCTOR_REFERENCE:
2794         case TypeReference.METHOD_REFERENCE:
2795           currentOffset += 3;
2796           break;
2797         case TypeReference.CLASS_TYPE_PARAMETER:
2798         case TypeReference.METHOD_TYPE_PARAMETER:
2799         case TypeReference.METHOD_FORMAL_PARAMETER:
2800         case TypeReference.FIELD:
2801         case TypeReference.METHOD_RETURN:
2802         case TypeReference.METHOD_RECEIVER:
2803         default:
2804           // TypeReference type which can't be used in Code attribute, or which is unknown.
2805           throw new IllegalArgumentException();
2806       }
2807       // Parse the rest of the type_annotation structure, starting with the target_path structure
2808       // (whose size depends on its path_length field).
2809       int pathLength = readByte(currentOffset);
2810       if ((targetType >>> 24) == TypeReference.EXCEPTION_PARAMETER) {
2811         // Parse the target_path structure and create a corresponding TypePath.
2812         TypePath path = pathLength == 0 ? null : new TypePath(classFileBuffer, currentOffset);
2813         currentOffset += 1 + 2 * pathLength;
2814         // Parse the type_index field.
2815         String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2816         currentOffset += 2;
2817         // Parse num_element_value_pairs and element_value_pairs and visit these values.
2818         currentOffset =
2819             readElementValues(
2820                 methodVisitor.visitTryCatchAnnotation(
2821                     targetType & 0xFFFFFF00, path, annotationDescriptor, visible),
2822                 currentOffset,
2823                 /* named = */ true,
2824                 charBuffer);
2825       } else {
2826         // We don't want to visit the other target_type annotations, so we just skip them (which
2827         // requires some parsing because the element_value_pairs array has a variable size). First,
2828         // skip the target_path structure:
2829         currentOffset += 3 + 2 * pathLength;
2830         // Then skip the num_element_value_pairs and element_value_pairs fields (by reading them
2831         // with a null AnnotationVisitor).
2832         currentOffset =
2833             readElementValues(
2834                 /* annotationVisitor = */ null, currentOffset, /* named = */ true, charBuffer);
2835       }
2836     }
2837     return typeAnnotationsOffsets;
2838   }
2839 
2840   /**
2841    * Returns the bytecode offset corresponding to the specified JVMS 'type_annotation' structure, or
2842    * -1 if there is no such type_annotation of if it does not have a bytecode offset.
2843    *
2844    * @param typeAnnotationOffsets the offset of each 'type_annotation' entry in a
2845    *     Runtime[In]VisibleTypeAnnotations attribute, or {@literal null}.
2846    * @param typeAnnotationIndex the index a 'type_annotation' entry in typeAnnotationOffsets.
2847    * @return bytecode offset corresponding to the specified JVMS 'type_annotation' structure, or -1
2848    *     if there is no such type_annotation of if it does not have a bytecode offset.
2849    */
2850   private int getTypeAnnotationBytecodeOffset(
2851       final int[] typeAnnotationOffsets, final int typeAnnotationIndex) {
2852     if (typeAnnotationOffsets == null
2853         || typeAnnotationIndex >= typeAnnotationOffsets.length
2854         || readByte(typeAnnotationOffsets[typeAnnotationIndex]) < TypeReference.INSTANCEOF) {
2855       return -1;
2856     }
2857     return readUnsignedShort(typeAnnotationOffsets[typeAnnotationIndex] + 1);
2858   }
2859 
2860   /**
2861    * Parses the header of a JVMS type_annotation structure to extract its target_type, target_info
2862    * and target_path (the result is stored in the given context), and returns the start offset of
2863    * the rest of the type_annotation structure.
2864    *
2865    * @param context information about the class being parsed. This is where the extracted
2866    *     target_type and target_path must be stored.
2867    * @param typeAnnotationOffset the start offset of a type_annotation structure.
2868    * @return the start offset of the rest of the type_annotation structure.
2869    */
2870   private int readTypeAnnotationTarget(final Context context, final int typeAnnotationOffset) {
2871     int currentOffset = typeAnnotationOffset;
2872     // Parse and store the target_type structure.
2873     int targetType = readInt(typeAnnotationOffset);
2874     switch (targetType >>> 24) {
2875       case TypeReference.CLASS_TYPE_PARAMETER:
2876       case TypeReference.METHOD_TYPE_PARAMETER:
2877       case TypeReference.METHOD_FORMAL_PARAMETER:
2878         targetType &= 0xFFFF0000;
2879         currentOffset += 2;
2880         break;
2881       case TypeReference.FIELD:
2882       case TypeReference.METHOD_RETURN:
2883       case TypeReference.METHOD_RECEIVER:
2884         targetType &= 0xFF000000;
2885         currentOffset += 1;
2886         break;
2887       case TypeReference.LOCAL_VARIABLE:
2888       case TypeReference.RESOURCE_VARIABLE:
2889         targetType &= 0xFF000000;
2890         int tableLength = readUnsignedShort(currentOffset + 1);
2891         currentOffset += 3;
2892         context.currentLocalVariableAnnotationRangeStarts = new Label[tableLength];
2893         context.currentLocalVariableAnnotationRangeEnds = new Label[tableLength];
2894         context.currentLocalVariableAnnotationRangeIndices = new int[tableLength];
2895         for (int i = 0; i < tableLength; ++i) {
2896           int startPc = readUnsignedShort(currentOffset);
2897           int length = readUnsignedShort(currentOffset + 2);
2898           int index = readUnsignedShort(currentOffset + 4);
2899           currentOffset += 6;
2900           context.currentLocalVariableAnnotationRangeStarts[i] =
2901               createLabel(startPc, context.currentMethodLabels);
2902           context.currentLocalVariableAnnotationRangeEnds[i] =
2903               createLabel(startPc + length, context.currentMethodLabels);
2904           context.currentLocalVariableAnnotationRangeIndices[i] = index;
2905         }
2906         break;
2907       case TypeReference.CAST:
2908       case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
2909       case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
2910       case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
2911       case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
2912         targetType &= 0xFF0000FF;
2913         currentOffset += 4;
2914         break;
2915       case TypeReference.CLASS_EXTENDS:
2916       case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
2917       case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
2918       case TypeReference.THROWS:
2919       case TypeReference.EXCEPTION_PARAMETER:
2920         targetType &= 0xFFFFFF00;
2921         currentOffset += 3;
2922         break;
2923       case TypeReference.INSTANCEOF:
2924       case TypeReference.NEW:
2925       case TypeReference.CONSTRUCTOR_REFERENCE:
2926       case TypeReference.METHOD_REFERENCE:
2927         targetType &= 0xFF000000;
2928         currentOffset += 3;
2929         break;
2930       default:
2931         throw new IllegalArgumentException();
2932     }
2933     context.currentTypeAnnotationTarget = targetType;
2934     // Parse and store the target_path structure.
2935     int pathLength = readByte(currentOffset);
2936     context.currentTypeAnnotationTargetPath =
2937         pathLength == 0 ? null : new TypePath(classFileBuffer, currentOffset);
2938     // Return the start offset of the rest of the type_annotation structure.
2939     return currentOffset + 1 + 2 * pathLength;
2940   }
2941 
2942   /**
2943    * Reads a Runtime[In]VisibleParameterAnnotations attribute and makes the given visitor visit it.
2944    *
2945    * @param methodVisitor the visitor that must visit the parameter annotations.
2946    * @param context information about the class being parsed.
2947    * @param runtimeParameterAnnotationsOffset the start offset of a
2948    *     Runtime[In]VisibleParameterAnnotations attribute, excluding the attribute_info's
2949    *     attribute_name_index and attribute_length fields.
2950    * @param visible true if the attribute to parse is a RuntimeVisibleParameterAnnotations
2951    *     attribute, false it is a RuntimeInvisibleParameterAnnotations attribute.
2952    */
readParameterAnnotations( final MethodVisitor methodVisitor, final Context context, final int runtimeParameterAnnotationsOffset, final boolean visible)2953   private void readParameterAnnotations(
2954       final MethodVisitor methodVisitor,
2955       final Context context,
2956       final int runtimeParameterAnnotationsOffset,
2957       final boolean visible) {
2958     int currentOffset = runtimeParameterAnnotationsOffset;
2959     int numParameters = classFileBuffer[currentOffset++] & 0xFF;
2960     methodVisitor.visitAnnotableParameterCount(numParameters, visible);
2961     char[] charBuffer = context.charBuffer;
2962     for (int i = 0; i < numParameters; ++i) {
2963       int numAnnotations = readUnsignedShort(currentOffset);
2964       currentOffset += 2;
2965       while (numAnnotations-- > 0) {
2966         // Parse the type_index field.
2967         String annotationDescriptor = readUTF8(currentOffset, charBuffer);
2968         currentOffset += 2;
2969         // Parse num_element_value_pairs and element_value_pairs and visit these values.
2970         currentOffset =
2971             readElementValues(
2972                 methodVisitor.visitParameterAnnotation(i, annotationDescriptor, visible),
2973                 currentOffset,
2974                 /* named = */ true,
2975                 charBuffer);
2976       }
2977     }
2978   }
2979 
2980   /**
2981    * Reads the element values of a JVMS 'annotation' structure and makes the given visitor visit
2982    * them. This method can also be used to read the values of the JVMS 'array_value' field of an
2983    * annotation's 'element_value'.
2984    *
2985    * @param annotationVisitor the visitor that must visit the values.
2986    * @param annotationOffset the start offset of an 'annotation' structure (excluding its type_index
2987    *     field) or of an 'array_value' structure.
2988    * @param named if the annotation values are named or not. This should be true to parse the values
2989    *     of a JVMS 'annotation' structure, and false to parse the JVMS 'array_value' of an
2990    *     annotation's element_value.
2991    * @param charBuffer the buffer used to read strings in the constant pool.
2992    * @return the end offset of the JVMS 'annotation' or 'array_value' structure.
2993    */
readElementValues( final AnnotationVisitor annotationVisitor, final int annotationOffset, final boolean named, final char[] charBuffer)2994   private int readElementValues(
2995       final AnnotationVisitor annotationVisitor,
2996       final int annotationOffset,
2997       final boolean named,
2998       final char[] charBuffer) {
2999     int currentOffset = annotationOffset;
3000     // Read the num_element_value_pairs field (or num_values field for an array_value).
3001     int numElementValuePairs = readUnsignedShort(currentOffset);
3002     currentOffset += 2;
3003     if (named) {
3004       // Parse the element_value_pairs array.
3005       while (numElementValuePairs-- > 0) {
3006         String elementName = readUTF8(currentOffset, charBuffer);
3007         currentOffset =
3008             readElementValue(annotationVisitor, currentOffset + 2, elementName, charBuffer);
3009       }
3010     } else {
3011       // Parse the array_value array.
3012       while (numElementValuePairs-- > 0) {
3013         currentOffset =
3014             readElementValue(annotationVisitor, currentOffset, /* elementName= */ null, charBuffer);
3015       }
3016     }
3017     if (annotationVisitor != null) {
3018       annotationVisitor.visitEnd();
3019     }
3020     return currentOffset;
3021   }
3022 
3023   /**
3024    * Reads a JVMS 'element_value' structure and makes the given visitor visit it.
3025    *
3026    * @param annotationVisitor the visitor that must visit the element_value structure.
3027    * @param elementValueOffset the start offset in {@link #classFileBuffer} of the element_value
3028    *     structure to be read.
3029    * @param elementName the name of the element_value structure to be read, or {@literal null}.
3030    * @param charBuffer the buffer used to read strings in the constant pool.
3031    * @return the end offset of the JVMS 'element_value' structure.
3032    */
readElementValue( final AnnotationVisitor annotationVisitor, final int elementValueOffset, final String elementName, final char[] charBuffer)3033   private int readElementValue(
3034       final AnnotationVisitor annotationVisitor,
3035       final int elementValueOffset,
3036       final String elementName,
3037       final char[] charBuffer) {
3038     int currentOffset = elementValueOffset;
3039     if (annotationVisitor == null) {
3040       switch (classFileBuffer[currentOffset] & 0xFF) {
3041         case 'e': // enum_const_value
3042           return currentOffset + 5;
3043         case '@': // annotation_value
3044           return readElementValues(null, currentOffset + 3, /* named = */ true, charBuffer);
3045         case '[': // array_value
3046           return readElementValues(null, currentOffset + 1, /* named = */ false, charBuffer);
3047         default:
3048           return currentOffset + 3;
3049       }
3050     }
3051     switch (classFileBuffer[currentOffset++] & 0xFF) {
3052       case 'B': // const_value_index, CONSTANT_Integer
3053         annotationVisitor.visit(
3054             elementName, (byte) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
3055         currentOffset += 2;
3056         break;
3057       case 'C': // const_value_index, CONSTANT_Integer
3058         annotationVisitor.visit(
3059             elementName, (char) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
3060         currentOffset += 2;
3061         break;
3062       case 'D': // const_value_index, CONSTANT_Double
3063       case 'F': // const_value_index, CONSTANT_Float
3064       case 'I': // const_value_index, CONSTANT_Integer
3065       case 'J': // const_value_index, CONSTANT_Long
3066         annotationVisitor.visit(
3067             elementName, readConst(readUnsignedShort(currentOffset), charBuffer));
3068         currentOffset += 2;
3069         break;
3070       case 'S': // const_value_index, CONSTANT_Integer
3071         annotationVisitor.visit(
3072             elementName, (short) readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]));
3073         currentOffset += 2;
3074         break;
3075 
3076       case 'Z': // const_value_index, CONSTANT_Integer
3077         annotationVisitor.visit(
3078             elementName,
3079             readInt(cpInfoOffsets[readUnsignedShort(currentOffset)]) == 0
3080                 ? Boolean.FALSE
3081                 : Boolean.TRUE);
3082         currentOffset += 2;
3083         break;
3084       case 's': // const_value_index, CONSTANT_Utf8
3085         annotationVisitor.visit(elementName, readUTF8(currentOffset, charBuffer));
3086         currentOffset += 2;
3087         break;
3088       case 'e': // enum_const_value
3089         annotationVisitor.visitEnum(
3090             elementName,
3091             readUTF8(currentOffset, charBuffer),
3092             readUTF8(currentOffset + 2, charBuffer));
3093         currentOffset += 4;
3094         break;
3095       case 'c': // class_info
3096         annotationVisitor.visit(elementName, Type.getType(readUTF8(currentOffset, charBuffer)));
3097         currentOffset += 2;
3098         break;
3099       case '@': // annotation_value
3100         currentOffset =
3101             readElementValues(
3102                 annotationVisitor.visitAnnotation(elementName, readUTF8(currentOffset, charBuffer)),
3103                 currentOffset + 2,
3104                 true,
3105                 charBuffer);
3106         break;
3107       case '[': // array_value
3108         int numValues = readUnsignedShort(currentOffset);
3109         currentOffset += 2;
3110         if (numValues == 0) {
3111           return readElementValues(
3112               annotationVisitor.visitArray(elementName),
3113               currentOffset - 2,
3114               /* named = */ false,
3115               charBuffer);
3116         }
3117         switch (classFileBuffer[currentOffset] & 0xFF) {
3118           case 'B':
3119             byte[] byteValues = new byte[numValues];
3120             for (int i = 0; i < numValues; i++) {
3121               byteValues[i] = (byte) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3122               currentOffset += 3;
3123             }
3124             annotationVisitor.visit(elementName, byteValues);
3125             break;
3126           case 'Z':
3127             boolean[] booleanValues = new boolean[numValues];
3128             for (int i = 0; i < numValues; i++) {
3129               booleanValues[i] = readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]) != 0;
3130               currentOffset += 3;
3131             }
3132             annotationVisitor.visit(elementName, booleanValues);
3133             break;
3134           case 'S':
3135             short[] shortValues = new short[numValues];
3136             for (int i = 0; i < numValues; i++) {
3137               shortValues[i] = (short) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3138               currentOffset += 3;
3139             }
3140             annotationVisitor.visit(elementName, shortValues);
3141             break;
3142           case 'C':
3143             char[] charValues = new char[numValues];
3144             for (int i = 0; i < numValues; i++) {
3145               charValues[i] = (char) readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3146               currentOffset += 3;
3147             }
3148             annotationVisitor.visit(elementName, charValues);
3149             break;
3150           case 'I':
3151             int[] intValues = new int[numValues];
3152             for (int i = 0; i < numValues; i++) {
3153               intValues[i] = readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3154               currentOffset += 3;
3155             }
3156             annotationVisitor.visit(elementName, intValues);
3157             break;
3158           case 'J':
3159             long[] longValues = new long[numValues];
3160             for (int i = 0; i < numValues; i++) {
3161               longValues[i] = readLong(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]);
3162               currentOffset += 3;
3163             }
3164             annotationVisitor.visit(elementName, longValues);
3165             break;
3166           case 'F':
3167             float[] floatValues = new float[numValues];
3168             for (int i = 0; i < numValues; i++) {
3169               floatValues[i] =
3170                   Float.intBitsToFloat(
3171                       readInt(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]));
3172               currentOffset += 3;
3173             }
3174             annotationVisitor.visit(elementName, floatValues);
3175             break;
3176           case 'D':
3177             double[] doubleValues = new double[numValues];
3178             for (int i = 0; i < numValues; i++) {
3179               doubleValues[i] =
3180                   Double.longBitsToDouble(
3181                       readLong(cpInfoOffsets[readUnsignedShort(currentOffset + 1)]));
3182               currentOffset += 3;
3183             }
3184             annotationVisitor.visit(elementName, doubleValues);
3185             break;
3186           default:
3187             currentOffset =
3188                 readElementValues(
3189                     annotationVisitor.visitArray(elementName),
3190                     currentOffset - 2,
3191                     /* named = */ false,
3192                     charBuffer);
3193             break;
3194         }
3195         break;
3196       default:
3197         throw new IllegalArgumentException();
3198     }
3199     return currentOffset;
3200   }
3201 
3202   // ----------------------------------------------------------------------------------------------
3203   // Methods to parse stack map frames
3204   // ----------------------------------------------------------------------------------------------
3205 
3206   /**
3207    * Computes the implicit frame of the method currently being parsed (as defined in the given
3208    * {@link Context}) and stores it in the given context.
3209    *
3210    * @param context information about the class being parsed.
3211    */
computeImplicitFrame(final Context context)3212   private void computeImplicitFrame(final Context context) {
3213     String methodDescriptor = context.currentMethodDescriptor;
3214     Object[] locals = context.currentFrameLocalTypes;
3215     int numLocal = 0;
3216     if ((context.currentMethodAccessFlags & Opcodes.ACC_STATIC) == 0) {
3217       if ("<init>".equals(context.currentMethodName)) {
3218         locals[numLocal++] = Opcodes.UNINITIALIZED_THIS;
3219       } else {
3220         locals[numLocal++] = readClass(header + 2, context.charBuffer);
3221       }
3222     }
3223     // Parse the method descriptor, one argument type descriptor at each iteration. Start by
3224     // skipping the first method descriptor character, which is always '('.
3225     int currentMethodDescritorOffset = 1;
3226     while (true) {
3227       int currentArgumentDescriptorStartOffset = currentMethodDescritorOffset;
3228       switch (methodDescriptor.charAt(currentMethodDescritorOffset++)) {
3229         case 'Z':
3230         case 'C':
3231         case 'B':
3232         case 'S':
3233         case 'I':
3234           locals[numLocal++] = Opcodes.INTEGER;
3235           break;
3236         case 'F':
3237           locals[numLocal++] = Opcodes.FLOAT;
3238           break;
3239         case 'J':
3240           locals[numLocal++] = Opcodes.LONG;
3241           break;
3242         case 'D':
3243           locals[numLocal++] = Opcodes.DOUBLE;
3244           break;
3245         case '[':
3246           while (methodDescriptor.charAt(currentMethodDescritorOffset) == '[') {
3247             ++currentMethodDescritorOffset;
3248           }
3249           if (methodDescriptor.charAt(currentMethodDescritorOffset) == 'L') {
3250             ++currentMethodDescritorOffset;
3251             while (methodDescriptor.charAt(currentMethodDescritorOffset) != ';') {
3252               ++currentMethodDescritorOffset;
3253             }
3254           }
3255           locals[numLocal++] =
3256               methodDescriptor.substring(
3257                   currentArgumentDescriptorStartOffset, ++currentMethodDescritorOffset);
3258           break;
3259         case 'L':
3260           while (methodDescriptor.charAt(currentMethodDescritorOffset) != ';') {
3261             ++currentMethodDescritorOffset;
3262           }
3263           locals[numLocal++] =
3264               methodDescriptor.substring(
3265                   currentArgumentDescriptorStartOffset + 1, currentMethodDescritorOffset++);
3266           break;
3267         default:
3268           context.currentFrameLocalCount = numLocal;
3269           return;
3270       }
3271     }
3272   }
3273 
3274   /**
3275    * Reads a JVMS 'stack_map_frame' structure and stores the result in the given {@link Context}
3276    * object. This method can also be used to read a full_frame structure, excluding its frame_type
3277    * field (this is used to parse the legacy StackMap attributes).
3278    *
3279    * @param stackMapFrameOffset the start offset in {@link #classFileBuffer} of the
3280    *     stack_map_frame_value structure to be read, or the start offset of a full_frame structure
3281    *     (excluding its frame_type field).
3282    * @param compressed true to read a 'stack_map_frame' structure, false to read a 'full_frame'
3283    *     structure without its frame_type field.
3284    * @param expand if the stack map frame must be expanded. See {@link #EXPAND_FRAMES}.
3285    * @param context where the parsed stack map frame must be stored.
3286    * @return the end offset of the JVMS 'stack_map_frame' or 'full_frame' structure.
3287    */
readStackMapFrame( final int stackMapFrameOffset, final boolean compressed, final boolean expand, final Context context)3288   private int readStackMapFrame(
3289       final int stackMapFrameOffset,
3290       final boolean compressed,
3291       final boolean expand,
3292       final Context context) {
3293     int currentOffset = stackMapFrameOffset;
3294     final char[] charBuffer = context.charBuffer;
3295     final Label[] labels = context.currentMethodLabels;
3296     int frameType;
3297     if (compressed) {
3298       // Read the frame_type field.
3299       frameType = classFileBuffer[currentOffset++] & 0xFF;
3300     } else {
3301       frameType = Frame.FULL_FRAME;
3302       context.currentFrameOffset = -1;
3303     }
3304     int offsetDelta;
3305     context.currentFrameLocalCountDelta = 0;
3306     if (frameType < Frame.SAME_LOCALS_1_STACK_ITEM_FRAME) {
3307       offsetDelta = frameType;
3308       context.currentFrameType = Opcodes.F_SAME;
3309       context.currentFrameStackCount = 0;
3310     } else if (frameType < Frame.RESERVED) {
3311       offsetDelta = frameType - Frame.SAME_LOCALS_1_STACK_ITEM_FRAME;
3312       currentOffset =
3313           readVerificationTypeInfo(
3314               currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels);
3315       context.currentFrameType = Opcodes.F_SAME1;
3316       context.currentFrameStackCount = 1;
3317     } else if (frameType >= Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
3318       offsetDelta = readUnsignedShort(currentOffset);
3319       currentOffset += 2;
3320       if (frameType == Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
3321         currentOffset =
3322             readVerificationTypeInfo(
3323                 currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels);
3324         context.currentFrameType = Opcodes.F_SAME1;
3325         context.currentFrameStackCount = 1;
3326       } else if (frameType >= Frame.CHOP_FRAME && frameType < Frame.SAME_FRAME_EXTENDED) {
3327         context.currentFrameType = Opcodes.F_CHOP;
3328         context.currentFrameLocalCountDelta = Frame.SAME_FRAME_EXTENDED - frameType;
3329         context.currentFrameLocalCount -= context.currentFrameLocalCountDelta;
3330         context.currentFrameStackCount = 0;
3331       } else if (frameType == Frame.SAME_FRAME_EXTENDED) {
3332         context.currentFrameType = Opcodes.F_SAME;
3333         context.currentFrameStackCount = 0;
3334       } else if (frameType < Frame.FULL_FRAME) {
3335         int local = expand ? context.currentFrameLocalCount : 0;
3336         for (int k = frameType - Frame.SAME_FRAME_EXTENDED; k > 0; k--) {
3337           currentOffset =
3338               readVerificationTypeInfo(
3339                   currentOffset, context.currentFrameLocalTypes, local++, charBuffer, labels);
3340         }
3341         context.currentFrameType = Opcodes.F_APPEND;
3342         context.currentFrameLocalCountDelta = frameType - Frame.SAME_FRAME_EXTENDED;
3343         context.currentFrameLocalCount += context.currentFrameLocalCountDelta;
3344         context.currentFrameStackCount = 0;
3345       } else {
3346         final int numberOfLocals = readUnsignedShort(currentOffset);
3347         currentOffset += 2;
3348         context.currentFrameType = Opcodes.F_FULL;
3349         context.currentFrameLocalCountDelta = numberOfLocals;
3350         context.currentFrameLocalCount = numberOfLocals;
3351         for (int local = 0; local < numberOfLocals; ++local) {
3352           currentOffset =
3353               readVerificationTypeInfo(
3354                   currentOffset, context.currentFrameLocalTypes, local, charBuffer, labels);
3355         }
3356         final int numberOfStackItems = readUnsignedShort(currentOffset);
3357         currentOffset += 2;
3358         context.currentFrameStackCount = numberOfStackItems;
3359         for (int stack = 0; stack < numberOfStackItems; ++stack) {
3360           currentOffset =
3361               readVerificationTypeInfo(
3362                   currentOffset, context.currentFrameStackTypes, stack, charBuffer, labels);
3363         }
3364       }
3365     } else {
3366       throw new IllegalArgumentException();
3367     }
3368     context.currentFrameOffset += offsetDelta + 1;
3369     createLabel(context.currentFrameOffset, labels);
3370     return currentOffset;
3371   }
3372 
3373   /**
3374    * Reads a JVMS 'verification_type_info' structure and stores it at the given index in the given
3375    * array.
3376    *
3377    * @param verificationTypeInfoOffset the start offset of the 'verification_type_info' structure to
3378    *     read.
3379    * @param frame the array where the parsed type must be stored.
3380    * @param index the index in 'frame' where the parsed type must be stored.
3381    * @param charBuffer the buffer used to read strings in the constant pool.
3382    * @param labels the labels of the method currently being parsed, indexed by their offset. If the
3383    *     parsed type is an ITEM_Uninitialized, a new label for the corresponding NEW instruction is
3384    *     stored in this array if it does not already exist.
3385    * @return the end offset of the JVMS 'verification_type_info' structure.
3386    */
readVerificationTypeInfo( final int verificationTypeInfoOffset, final Object[] frame, final int index, final char[] charBuffer, final Label[] labels)3387   private int readVerificationTypeInfo(
3388       final int verificationTypeInfoOffset,
3389       final Object[] frame,
3390       final int index,
3391       final char[] charBuffer,
3392       final Label[] labels) {
3393     int currentOffset = verificationTypeInfoOffset;
3394     int tag = classFileBuffer[currentOffset++] & 0xFF;
3395     switch (tag) {
3396       case Frame.ITEM_TOP:
3397         frame[index] = Opcodes.TOP;
3398         break;
3399       case Frame.ITEM_INTEGER:
3400         frame[index] = Opcodes.INTEGER;
3401         break;
3402       case Frame.ITEM_FLOAT:
3403         frame[index] = Opcodes.FLOAT;
3404         break;
3405       case Frame.ITEM_DOUBLE:
3406         frame[index] = Opcodes.DOUBLE;
3407         break;
3408       case Frame.ITEM_LONG:
3409         frame[index] = Opcodes.LONG;
3410         break;
3411       case Frame.ITEM_NULL:
3412         frame[index] = Opcodes.NULL;
3413         break;
3414       case Frame.ITEM_UNINITIALIZED_THIS:
3415         frame[index] = Opcodes.UNINITIALIZED_THIS;
3416         break;
3417       case Frame.ITEM_OBJECT:
3418         frame[index] = readClass(currentOffset, charBuffer);
3419         currentOffset += 2;
3420         break;
3421       case Frame.ITEM_UNINITIALIZED:
3422         frame[index] = createLabel(readUnsignedShort(currentOffset), labels);
3423         currentOffset += 2;
3424         break;
3425       default:
3426         throw new IllegalArgumentException();
3427     }
3428     return currentOffset;
3429   }
3430 
3431   // ----------------------------------------------------------------------------------------------
3432   // Methods to parse attributes
3433   // ----------------------------------------------------------------------------------------------
3434 
3435   /**
3436    * Returns the offset in {@link #classFileBuffer} of the first ClassFile's 'attributes' array
3437    * field entry.
3438    *
3439    * @return the offset in {@link #classFileBuffer} of the first ClassFile's 'attributes' array
3440    *     field entry.
3441    */
getFirstAttributeOffset()3442   final int getFirstAttributeOffset() {
3443     // Skip the access_flags, this_class, super_class, and interfaces_count fields (using 2 bytes
3444     // each), as well as the interfaces array field (2 bytes per interface).
3445     int currentOffset = header + 8 + readUnsignedShort(header + 6) * 2;
3446 
3447     // Read the fields_count field.
3448     int fieldsCount = readUnsignedShort(currentOffset);
3449     currentOffset += 2;
3450     // Skip the 'fields' array field.
3451     while (fieldsCount-- > 0) {
3452       // Invariant: currentOffset is the offset of a field_info structure.
3453       // Skip the access_flags, name_index and descriptor_index fields (2 bytes each), and read the
3454       // attributes_count field.
3455       int attributesCount = readUnsignedShort(currentOffset + 6);
3456       currentOffset += 8;
3457       // Skip the 'attributes' array field.
3458       while (attributesCount-- > 0) {
3459         // Invariant: currentOffset is the offset of an attribute_info structure.
3460         // Read the attribute_length field (2 bytes after the start of the attribute_info) and skip
3461         // this many bytes, plus 6 for the attribute_name_index and attribute_length fields
3462         // (yielding the total size of the attribute_info structure).
3463         currentOffset += 6 + readInt(currentOffset + 2);
3464       }
3465     }
3466 
3467     // Skip the methods_count and 'methods' fields, using the same method as above.
3468     int methodsCount = readUnsignedShort(currentOffset);
3469     currentOffset += 2;
3470     while (methodsCount-- > 0) {
3471       int attributesCount = readUnsignedShort(currentOffset + 6);
3472       currentOffset += 8;
3473       while (attributesCount-- > 0) {
3474         currentOffset += 6 + readInt(currentOffset + 2);
3475       }
3476     }
3477 
3478     // Skip the ClassFile's attributes_count field.
3479     return currentOffset + 2;
3480   }
3481 
3482   /**
3483    * Reads the BootstrapMethods attribute to compute the offset of each bootstrap method.
3484    *
3485    * @param maxStringLength a conservative estimate of the maximum length of the strings contained
3486    *     in the constant pool of the class.
3487    * @return the offsets of the bootstrap methods.
3488    */
readBootstrapMethodsAttribute(final int maxStringLength)3489   private int[] readBootstrapMethodsAttribute(final int maxStringLength) {
3490     char[] charBuffer = new char[maxStringLength];
3491     int currentAttributeOffset = getFirstAttributeOffset();
3492     for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) {
3493       // Read the attribute_info's attribute_name and attribute_length fields.
3494       String attributeName = readUTF8(currentAttributeOffset, charBuffer);
3495       int attributeLength = readInt(currentAttributeOffset + 2);
3496       currentAttributeOffset += 6;
3497       if (Constants.BOOTSTRAP_METHODS.equals(attributeName)) {
3498         // Read the num_bootstrap_methods field and create an array of this size.
3499         int[] result = new int[readUnsignedShort(currentAttributeOffset)];
3500         // Compute and store the offset of each 'bootstrap_methods' array field entry.
3501         int currentBootstrapMethodOffset = currentAttributeOffset + 2;
3502         for (int j = 0; j < result.length; ++j) {
3503           result[j] = currentBootstrapMethodOffset;
3504           // Skip the bootstrap_method_ref and num_bootstrap_arguments fields (2 bytes each),
3505           // as well as the bootstrap_arguments array field (of size num_bootstrap_arguments * 2).
3506           currentBootstrapMethodOffset +=
3507               4 + readUnsignedShort(currentBootstrapMethodOffset + 2) * 2;
3508         }
3509         return result;
3510       }
3511       currentAttributeOffset += attributeLength;
3512     }
3513     throw new IllegalArgumentException();
3514   }
3515 
3516   /**
3517    * Reads a non standard JVMS 'attribute' structure in {@link #classFileBuffer}.
3518    *
3519    * @param attributePrototypes prototypes of the attributes that must be parsed during the visit of
3520    *     the class. Any attribute whose type is not equal to the type of one the prototypes will not
3521    *     be parsed: its byte array value will be passed unchanged to the ClassWriter.
3522    * @param type the type of the attribute.
3523    * @param offset the start offset of the JVMS 'attribute' structure in {@link #classFileBuffer}.
3524    *     The 6 attribute header bytes (attribute_name_index and attribute_length) are not taken into
3525    *     account here.
3526    * @param length the length of the attribute's content (excluding the 6 attribute header bytes).
3527    * @param charBuffer the buffer to be used to read strings in the constant pool.
3528    * @param codeAttributeOffset the start offset of the enclosing Code attribute in {@link
3529    *     #classFileBuffer}, or -1 if the attribute to be read is not a code attribute. The 6
3530    *     attribute header bytes (attribute_name_index and attribute_length) are not taken into
3531    *     account here.
3532    * @param labels the labels of the method's code, or {@literal null} if the attribute to be read
3533    *     is not a code attribute.
3534    * @return the attribute that has been read.
3535    */
readAttribute( final Attribute[] attributePrototypes, final String type, final int offset, final int length, final char[] charBuffer, final int codeAttributeOffset, final Label[] labels)3536   private Attribute readAttribute(
3537       final Attribute[] attributePrototypes,
3538       final String type,
3539       final int offset,
3540       final int length,
3541       final char[] charBuffer,
3542       final int codeAttributeOffset,
3543       final Label[] labels) {
3544     for (Attribute attributePrototype : attributePrototypes) {
3545       if (attributePrototype.type.equals(type)) {
3546         return attributePrototype.read(
3547             this, offset, length, charBuffer, codeAttributeOffset, labels);
3548       }
3549     }
3550     return new Attribute(type).read(this, offset, length, null, -1, null);
3551   }
3552 
3553   // -----------------------------------------------------------------------------------------------
3554   // Utility methods: low level parsing
3555   // -----------------------------------------------------------------------------------------------
3556 
3557   /**
3558    * Returns the number of entries in the class's constant pool table.
3559    *
3560    * @return the number of entries in the class's constant pool table.
3561    */
getItemCount()3562   public int getItemCount() {
3563     return cpInfoOffsets.length;
3564   }
3565 
3566   /**
3567    * Returns the start offset in this {@link ClassReader} of a JVMS 'cp_info' structure (i.e. a
3568    * constant pool entry), plus one. <i>This method is intended for {@link Attribute} sub classes,
3569    * and is normally not needed by class generators or adapters.</i>
3570    *
3571    * @param constantPoolEntryIndex the index a constant pool entry in the class's constant pool
3572    *     table.
3573    * @return the start offset in this {@link ClassReader} of the corresponding JVMS 'cp_info'
3574    *     structure, plus one.
3575    */
getItem(final int constantPoolEntryIndex)3576   public int getItem(final int constantPoolEntryIndex) {
3577     return cpInfoOffsets[constantPoolEntryIndex];
3578   }
3579 
3580   /**
3581    * Returns a conservative estimate of the maximum length of the strings contained in the class's
3582    * constant pool table.
3583    *
3584    * @return a conservative estimate of the maximum length of the strings contained in the class's
3585    *     constant pool table.
3586    */
getMaxStringLength()3587   public int getMaxStringLength() {
3588     return maxStringLength;
3589   }
3590 
3591   /**
3592    * Reads a byte value in this {@link ClassReader}. <i>This method is intended for {@link
3593    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3594    *
3595    * @param offset the start offset of the value to be read in this {@link ClassReader}.
3596    * @return the read value.
3597    */
readByte(final int offset)3598   public int readByte(final int offset) {
3599     return classFileBuffer[offset] & 0xFF;
3600   }
3601 
3602   /**
3603    * Reads an unsigned short value in this {@link ClassReader}. <i>This method is intended for
3604    * {@link Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3605    *
3606    * @param offset the start index of the value to be read in this {@link ClassReader}.
3607    * @return the read value.
3608    */
readUnsignedShort(final int offset)3609   public int readUnsignedShort(final int offset) {
3610     byte[] classBuffer = classFileBuffer;
3611     return ((classBuffer[offset] & 0xFF) << 8) | (classBuffer[offset + 1] & 0xFF);
3612   }
3613 
3614   /**
3615    * Reads a signed short value in this {@link ClassReader}. <i>This method is intended for {@link
3616    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3617    *
3618    * @param offset the start offset of the value to be read in this {@link ClassReader}.
3619    * @return the read value.
3620    */
readShort(final int offset)3621   public short readShort(final int offset) {
3622     byte[] classBuffer = classFileBuffer;
3623     return (short) (((classBuffer[offset] & 0xFF) << 8) | (classBuffer[offset + 1] & 0xFF));
3624   }
3625 
3626   /**
3627    * Reads a signed int 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    */
readInt(final int offset)3633   public int readInt(final int offset) {
3634     byte[] classBuffer = classFileBuffer;
3635     return ((classBuffer[offset] & 0xFF) << 24)
3636         | ((classBuffer[offset + 1] & 0xFF) << 16)
3637         | ((classBuffer[offset + 2] & 0xFF) << 8)
3638         | (classBuffer[offset + 3] & 0xFF);
3639   }
3640 
3641   /**
3642    * Reads a signed long value in this {@link ClassReader}. <i>This method is intended for {@link
3643    * Attribute} sub classes, and is normally not needed by class generators or adapters.</i>
3644    *
3645    * @param offset the start offset of the value to be read in this {@link ClassReader}.
3646    * @return the read value.
3647    */
readLong(final int offset)3648   public long readLong(final int offset) {
3649     long l1 = readInt(offset);
3650     long l0 = readInt(offset + 4) & 0xFFFFFFFFL;
3651     return (l1 << 32) | l0;
3652   }
3653 
3654   /**
3655    * Reads a CONSTANT_Utf8 constant pool entry in this {@link ClassReader}. <i>This method is
3656    * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3657    * adapters.</i>
3658    *
3659    * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3660    *     value is the index of a CONSTANT_Utf8 entry in the class's constant pool table.
3661    * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3662    *     large. It is not automatically resized.
3663    * @return the String corresponding to the specified CONSTANT_Utf8 entry.
3664    */
3665   // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).
readUTF8(final int offset, final char[] charBuffer)3666   public String readUTF8(final int offset, final char[] charBuffer) {
3667     int constantPoolEntryIndex = readUnsignedShort(offset);
3668     if (offset == 0 || constantPoolEntryIndex == 0) {
3669       return null;
3670     }
3671     return readUtf(constantPoolEntryIndex, charBuffer);
3672   }
3673 
3674   /**
3675    * Reads a CONSTANT_Utf8 constant pool entry in {@link #classFileBuffer}.
3676    *
3677    * @param constantPoolEntryIndex the index of a CONSTANT_Utf8 entry in the class's constant pool
3678    *     table.
3679    * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3680    *     large. It is not automatically resized.
3681    * @return the String corresponding to the specified CONSTANT_Utf8 entry.
3682    */
readUtf(final int constantPoolEntryIndex, final char[] charBuffer)3683   final String readUtf(final int constantPoolEntryIndex, final char[] charBuffer) {
3684     String value = constantUtf8Values[constantPoolEntryIndex];
3685     if (value != null) {
3686       return value;
3687     }
3688     int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3689     return constantUtf8Values[constantPoolEntryIndex] =
3690         readUtf(cpInfoOffset + 2, readUnsignedShort(cpInfoOffset), charBuffer);
3691   }
3692 
3693   /**
3694    * Reads an UTF8 string in {@link #classFileBuffer}.
3695    *
3696    * @param utfOffset the start offset of the UTF8 string to be read.
3697    * @param utfLength the length of the UTF8 string to be read.
3698    * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3699    *     large. It is not automatically resized.
3700    * @return the String corresponding to the specified UTF8 string.
3701    */
readUtf(final int utfOffset, final int utfLength, final char[] charBuffer)3702   private String readUtf(final int utfOffset, final int utfLength, final char[] charBuffer) {
3703     int currentOffset = utfOffset;
3704     int endOffset = currentOffset + utfLength;
3705     int strLength = 0;
3706     byte[] classBuffer = classFileBuffer;
3707     while (currentOffset < endOffset) {
3708       int currentByte = classBuffer[currentOffset++];
3709       if ((currentByte & 0x80) == 0) {
3710         charBuffer[strLength++] = (char) (currentByte & 0x7F);
3711       } else if ((currentByte & 0xE0) == 0xC0) {
3712         charBuffer[strLength++] =
3713             (char) (((currentByte & 0x1F) << 6) + (classBuffer[currentOffset++] & 0x3F));
3714       } else {
3715         charBuffer[strLength++] =
3716             (char)
3717                 (((currentByte & 0xF) << 12)
3718                     + ((classBuffer[currentOffset++] & 0x3F) << 6)
3719                     + (classBuffer[currentOffset++] & 0x3F));
3720       }
3721     }
3722     return new String(charBuffer, 0, strLength);
3723   }
3724 
3725   /**
3726    * Reads a CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType, CONSTANT_Module or
3727    * CONSTANT_Package constant pool entry in {@link #classFileBuffer}. <i>This method is intended
3728    * for {@link Attribute} sub classes, and is normally not needed by class generators or
3729    * adapters.</i>
3730    *
3731    * @param offset the start offset of an unsigned short value in {@link #classFileBuffer}, whose
3732    *     value is the index of a CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType,
3733    *     CONSTANT_Module or CONSTANT_Package entry in class's constant pool table.
3734    * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3735    *     large. It is not automatically resized.
3736    * @return the String corresponding to the specified constant pool entry.
3737    */
readStringish(final int offset, final char[] charBuffer)3738   private String readStringish(final int offset, final char[] charBuffer) {
3739     // Get the start offset of the cp_info structure (plus one), and read the CONSTANT_Utf8 entry
3740     // designated by the first two bytes of this cp_info.
3741     return readUTF8(cpInfoOffsets[readUnsignedShort(offset)], charBuffer);
3742   }
3743 
3744   /**
3745    * Reads a CONSTANT_Class 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_Class 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_Class entry.
3754    */
readClass(final int offset, final char[] charBuffer)3755   public String readClass(final int offset, final char[] charBuffer) {
3756     return readStringish(offset, charBuffer);
3757   }
3758 
3759   /**
3760    * Reads a CONSTANT_Module 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_Module 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_Module entry.
3769    */
readModule(final int offset, final char[] charBuffer)3770   public String readModule(final int offset, final char[] charBuffer) {
3771     return readStringish(offset, charBuffer);
3772   }
3773 
3774   /**
3775    * Reads a CONSTANT_Package constant pool entry in this {@link ClassReader}. <i>This method is
3776    * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3777    * adapters.</i>
3778    *
3779    * @param offset the start offset of an unsigned short value in this {@link ClassReader}, whose
3780    *     value is the index of a CONSTANT_Package entry in class's constant pool table.
3781    * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently
3782    *     large. It is not automatically resized.
3783    * @return the String corresponding to the specified CONSTANT_Package entry.
3784    */
readPackage(final int offset, final char[] charBuffer)3785   public String readPackage(final int offset, final char[] charBuffer) {
3786     return readStringish(offset, charBuffer);
3787   }
3788 
3789   /**
3790    * Reads a CONSTANT_Dynamic constant pool entry in {@link #classFileBuffer}.
3791    *
3792    * @param constantPoolEntryIndex the index of a CONSTANT_Dynamic entry in the class's constant
3793    *     pool table.
3794    * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently
3795    *     large. It is not automatically resized.
3796    * @return the ConstantDynamic corresponding to the specified CONSTANT_Dynamic entry.
3797    */
readConstantDynamic( final int constantPoolEntryIndex, final char[] charBuffer)3798   private ConstantDynamic readConstantDynamic(
3799       final int constantPoolEntryIndex, final char[] charBuffer) {
3800     ConstantDynamic constantDynamic = constantDynamicValues[constantPoolEntryIndex];
3801     if (constantDynamic != null) {
3802       return constantDynamic;
3803     }
3804     int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3805     int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 2)];
3806     String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
3807     String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
3808     int bootstrapMethodOffset = bootstrapMethodOffsets[readUnsignedShort(cpInfoOffset)];
3809     Handle handle = (Handle) readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
3810     Object[] bootstrapMethodArguments = new Object[readUnsignedShort(bootstrapMethodOffset + 2)];
3811     bootstrapMethodOffset += 4;
3812     for (int i = 0; i < bootstrapMethodArguments.length; i++) {
3813       bootstrapMethodArguments[i] = readConst(readUnsignedShort(bootstrapMethodOffset), charBuffer);
3814       bootstrapMethodOffset += 2;
3815     }
3816     return constantDynamicValues[constantPoolEntryIndex] =
3817         new ConstantDynamic(name, descriptor, handle, bootstrapMethodArguments);
3818   }
3819 
3820   /**
3821    * Reads a numeric or string constant pool entry in this {@link ClassReader}. <i>This method is
3822    * intended for {@link Attribute} sub classes, and is normally not needed by class generators or
3823    * adapters.</i>
3824    *
3825    * @param constantPoolEntryIndex the index of a CONSTANT_Integer, CONSTANT_Float, CONSTANT_Long,
3826    *     CONSTANT_Double, CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType,
3827    *     CONSTANT_MethodHandle or CONSTANT_Dynamic entry in the class's constant pool.
3828    * @param charBuffer the buffer to be used to read strings. This buffer must be sufficiently
3829    *     large. It is not automatically resized.
3830    * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, {@link String},
3831    *     {@link Type}, {@link Handle} or {@link ConstantDynamic} corresponding to the specified
3832    *     constant pool entry.
3833    */
readConst(final int constantPoolEntryIndex, final char[] charBuffer)3834   public Object readConst(final int constantPoolEntryIndex, final char[] charBuffer) {
3835     int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];
3836     switch (classFileBuffer[cpInfoOffset - 1]) {
3837       case Symbol.CONSTANT_INTEGER_TAG:
3838         return readInt(cpInfoOffset);
3839       case Symbol.CONSTANT_FLOAT_TAG:
3840         return Float.intBitsToFloat(readInt(cpInfoOffset));
3841       case Symbol.CONSTANT_LONG_TAG:
3842         return readLong(cpInfoOffset);
3843       case Symbol.CONSTANT_DOUBLE_TAG:
3844         return Double.longBitsToDouble(readLong(cpInfoOffset));
3845       case Symbol.CONSTANT_CLASS_TAG:
3846         return Type.getObjectType(readUTF8(cpInfoOffset, charBuffer));
3847       case Symbol.CONSTANT_STRING_TAG:
3848         return readUTF8(cpInfoOffset, charBuffer);
3849       case Symbol.CONSTANT_METHOD_TYPE_TAG:
3850         return Type.getMethodType(readUTF8(cpInfoOffset, charBuffer));
3851       case Symbol.CONSTANT_METHOD_HANDLE_TAG:
3852         int referenceKind = readByte(cpInfoOffset);
3853         int referenceCpInfoOffset = cpInfoOffsets[readUnsignedShort(cpInfoOffset + 1)];
3854         int nameAndTypeCpInfoOffset = cpInfoOffsets[readUnsignedShort(referenceCpInfoOffset + 2)];
3855         String owner = readClass(referenceCpInfoOffset, charBuffer);
3856         String name = readUTF8(nameAndTypeCpInfoOffset, charBuffer);
3857         String descriptor = readUTF8(nameAndTypeCpInfoOffset + 2, charBuffer);
3858         boolean isInterface =
3859             classFileBuffer[referenceCpInfoOffset - 1] == Symbol.CONSTANT_INTERFACE_METHODREF_TAG;
3860         return new Handle(referenceKind, owner, name, descriptor, isInterface);
3861       case Symbol.CONSTANT_DYNAMIC_TAG:
3862         return readConstantDynamic(constantPoolEntryIndex, charBuffer);
3863       default:
3864         throw new IllegalArgumentException();
3865     }
3866   }
3867 }
3868