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