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