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 */ 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 */ 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 */ 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.V19) { 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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") 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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). 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 }