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