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