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