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