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