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