001/*** 002 * ASM: a very small and fast Java bytecode manipulation framework 003 * Copyright (c) 2000-2011 INRIA, France Telecom 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions 008 * are met: 009 * 1. Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 2. Redistributions in binary form must reproduce the above copyright 012 * notice, this list of conditions and the following disclaimer in the 013 * documentation and/or other materials provided with the distribution. 014 * 3. Neither the name of the copyright holders nor the names of its 015 * contributors may be used to endorse or promote products derived from 016 * this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 028 * THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.springframework.asm; 031 032import java.io.IOException; 033import java.io.InputStream; 034 035/** 036 * A Java class parser to make a {@link ClassVisitor} visit an existing class. 037 * This class parses a byte array conforming to the Java class file format and 038 * calls the appropriate visit methods of a given class visitor for each field, 039 * method and bytecode instruction encountered. 040 * 041 * @author Eric Bruneton 042 * @author Eugene Kuleshov 043 */ 044public class ClassReader { 045 046 /** 047 * True to enable signatures support. 048 */ 049 static final boolean SIGNATURES = true; 050 051 /** 052 * True to enable annotations support. 053 */ 054 static final boolean ANNOTATIONS = true; 055 056 /** 057 * True to enable stack map frames support. 058 */ 059 static final boolean FRAMES = true; 060 061 /** 062 * True to enable bytecode writing support. 063 */ 064 static final boolean WRITER = true; 065 066 /** 067 * True to enable JSR_W and GOTO_W support. 068 */ 069 static final boolean RESIZE = true; 070 071 /** 072 * Flag to skip method code. If this class is set <code>CODE</code> 073 * attribute won't be visited. This can be used, for example, to retrieve 074 * annotations for methods and method parameters. 075 */ 076 public static final int SKIP_CODE = 1; 077 078 /** 079 * Flag to skip the debug information in the class. If this flag is set the 080 * debug information of the class is not visited, i.e. the 081 * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and 082 * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be 083 * called. 084 */ 085 public static final int SKIP_DEBUG = 2; 086 087 /** 088 * Flag to skip the stack map frames in the class. If this flag is set the 089 * stack map frames of the class is not visited, i.e. the 090 * {@link MethodVisitor#visitFrame visitFrame} method will not be called. 091 * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is 092 * used: it avoids visiting frames that will be ignored and recomputed from 093 * scratch in the class writer. 094 */ 095 public static final int SKIP_FRAMES = 4; 096 097 /** 098 * Flag to expand the stack map frames. By default stack map frames are 099 * visited in their original format (i.e. "expanded" for classes whose 100 * version is less than V1_6, and "compressed" for the other classes). If 101 * this flag is set, stack map frames are always visited in expanded format 102 * (this option adds a decompression/recompression step in ClassReader and 103 * ClassWriter which degrades performances quite a lot). 104 */ 105 public static final int EXPAND_FRAMES = 8; 106 107 /** 108 * Flag to expand the ASM pseudo instructions into an equivalent sequence of 109 * standard bytecode instructions. When resolving a forward jump it may 110 * happen that the signed 2 bytes offset reserved for it is not sufficient 111 * to store the bytecode offset. In this case the jump instruction is 112 * replaced with a temporary ASM pseudo instruction using an unsigned 2 113 * bytes offset (see Label#resolve). This internal flag is used to re-read 114 * classes containing such instructions, in order to replace them with 115 * standard instructions. In addition, when this flag is used, GOTO_W and 116 * JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that 117 * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and 118 * converted back to a GOTO_W in ClassWriter cannot occur. 119 */ 120 static final int EXPAND_ASM_INSNS = 256; 121 122 /** 123 * The class to be parsed. <i>The content of this array must not be 124 * modified. This field is intended for {@link Attribute} sub classes, and 125 * is normally not needed by class generators or adapters.</i> 126 */ 127 public final byte[] b; 128 129 /** 130 * The start index of each constant pool item in {@link #b b}, plus one. The 131 * one byte offset skips the constant pool item tag that indicates its type. 132 */ 133 private final int[] items; 134 135 /** 136 * The String objects corresponding to the CONSTANT_Utf8 items. This cache 137 * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, 138 * which GREATLY improves performances (by a factor 2 to 3). This caching 139 * strategy could be extended to all constant pool items, but its benefit 140 * would not be so great for these items (because they are much less 141 * expensive to parse than CONSTANT_Utf8 items). 142 */ 143 private final String[] strings; 144 145 /** 146 * Maximum length of the strings contained in the constant pool of the 147 * class. 148 */ 149 private final int maxStringLength; 150 151 /** 152 * Start index of the class header information (access, name...) in 153 * {@link #b b}. 154 */ 155 public final int header; 156 157 // ------------------------------------------------------------------------ 158 // Constructors 159 // ------------------------------------------------------------------------ 160 161 /** 162 * Constructs a new {@link ClassReader} object. 163 * 164 * @param b 165 * the bytecode of the class to be read. 166 */ 167 public ClassReader(final byte[] b) { 168 this(b, 0, b.length); 169 } 170 171 /** 172 * Constructs a new {@link ClassReader} object. 173 * 174 * @param b 175 * the bytecode of the class to be read. 176 * @param off 177 * the start offset of the class data. 178 * @param len 179 * the length of the class data. 180 */ 181 public ClassReader(final byte[] b, final int off, final int len) { 182 this.b = b; 183 // checks the class version 184 /* SPRING PATCH: REMOVED FOR FORWARD COMPATIBILITY WITH JDK 9 185 if (readShort(off + 6) > Opcodes.V1_8) { 186 throw new IllegalArgumentException(); 187 } 188 */ 189 // parses the constant pool 190 items = new int[readUnsignedShort(off + 8)]; 191 int n = items.length; 192 strings = new String[n]; 193 int max = 0; 194 int index = off + 10; 195 for (int i = 1; i < n; ++i) { 196 items[i] = index + 1; 197 int size; 198 switch (b[index]) { 199 case ClassWriter.FIELD: 200 case ClassWriter.METH: 201 case ClassWriter.IMETH: 202 case ClassWriter.INT: 203 case ClassWriter.FLOAT: 204 case ClassWriter.NAME_TYPE: 205 case ClassWriter.INDY: 206 size = 5; 207 break; 208 case ClassWriter.LONG: 209 case ClassWriter.DOUBLE: 210 size = 9; 211 ++i; 212 break; 213 case ClassWriter.UTF8: 214 size = 3 + readUnsignedShort(index + 1); 215 if (size > max) { 216 max = size; 217 } 218 break; 219 case ClassWriter.HANDLE: 220 size = 4; 221 break; 222 // case ClassWriter.CLASS: 223 // case ClassWriter.STR: 224 // case ClassWriter.MTYPE 225 // case ClassWriter.PACKAGE: 226 // case ClassWriter.MODULE: 227 default: 228 size = 3; 229 break; 230 } 231 index += size; 232 } 233 maxStringLength = max; 234 // the class header information starts just after the constant pool 235 header = index; 236 } 237 238 /** 239 * Returns the class's access flags (see {@link Opcodes}). This value may 240 * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 241 * and those flags are represented by attributes. 242 * 243 * @return the class access flags 244 * 245 * @see ClassVisitor#visit(int, int, String, String, String, String[]) 246 */ 247 public int getAccess() { 248 return readUnsignedShort(header); 249 } 250 251 /** 252 * Returns the internal name of the class (see 253 * {@link Type#getInternalName() getInternalName}). 254 * 255 * @return the internal class name 256 * 257 * @see ClassVisitor#visit(int, int, String, String, String, String[]) 258 */ 259 public String getClassName() { 260 return readClass(header + 2, new char[maxStringLength]); 261 } 262 263 /** 264 * Returns the internal of name of the super class (see 265 * {@link Type#getInternalName() getInternalName}). For interfaces, the 266 * super class is {@link Object}. 267 * 268 * @return the internal name of super class, or <tt>null</tt> for 269 * {@link Object} class. 270 * 271 * @see ClassVisitor#visit(int, int, String, String, String, String[]) 272 */ 273 public String getSuperName() { 274 return readClass(header + 4, new char[maxStringLength]); 275 } 276 277 /** 278 * Returns the internal names of the class's interfaces (see 279 * {@link Type#getInternalName() getInternalName}). 280 * 281 * @return the array of internal names for all implemented interfaces or 282 * <tt>null</tt>. 283 * 284 * @see ClassVisitor#visit(int, int, String, String, String, String[]) 285 */ 286 public String[] getInterfaces() { 287 int index = header + 6; 288 int n = readUnsignedShort(index); 289 String[] interfaces = new String[n]; 290 if (n > 0) { 291 char[] buf = new char[maxStringLength]; 292 for (int i = 0; i < n; ++i) { 293 index += 2; 294 interfaces[i] = readClass(index, buf); 295 } 296 } 297 return interfaces; 298 } 299 300 /** 301 * Copies the constant pool data into the given {@link ClassWriter}. Should 302 * be called before the {@link #accept(ClassVisitor,int)} method. 303 * 304 * @param classWriter 305 * the {@link ClassWriter} to copy constant pool into. 306 */ 307 void copyPool(final ClassWriter classWriter) { 308 char[] buf = new char[maxStringLength]; 309 int ll = items.length; 310 Item[] items2 = new Item[ll]; 311 for (int i = 1; i < ll; i++) { 312 int index = items[i]; 313 int tag = b[index - 1]; 314 Item item = new Item(i); 315 int nameType; 316 switch (tag) { 317 case ClassWriter.FIELD: 318 case ClassWriter.METH: 319 case ClassWriter.IMETH: 320 nameType = items[readUnsignedShort(index + 2)]; 321 item.set(tag, readClass(index, buf), readUTF8(nameType, buf), 322 readUTF8(nameType + 2, buf)); 323 break; 324 case ClassWriter.INT: 325 item.set(readInt(index)); 326 break; 327 case ClassWriter.FLOAT: 328 item.set(Float.intBitsToFloat(readInt(index))); 329 break; 330 case ClassWriter.NAME_TYPE: 331 item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), 332 null); 333 break; 334 case ClassWriter.LONG: 335 item.set(readLong(index)); 336 ++i; 337 break; 338 case ClassWriter.DOUBLE: 339 item.set(Double.longBitsToDouble(readLong(index))); 340 ++i; 341 break; 342 case ClassWriter.UTF8: { 343 String s = strings[i]; 344 if (s == null) { 345 index = items[i]; 346 s = strings[i] = readUTF(index + 2, 347 readUnsignedShort(index), buf); 348 } 349 item.set(tag, s, null, null); 350 break; 351 } 352 case ClassWriter.HANDLE: { 353 int fieldOrMethodRef = items[readUnsignedShort(index + 1)]; 354 nameType = items[readUnsignedShort(fieldOrMethodRef + 2)]; 355 item.set(ClassWriter.HANDLE_BASE + readByte(index), 356 readClass(fieldOrMethodRef, buf), 357 readUTF8(nameType, buf), readUTF8(nameType + 2, buf)); 358 break; 359 } 360 case ClassWriter.INDY: 361 if (classWriter.bootstrapMethods == null) { 362 copyBootstrapMethods(classWriter, items2, buf); 363 } 364 nameType = items[readUnsignedShort(index + 2)]; 365 item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf), 366 readUnsignedShort(index)); 367 break; 368 // case ClassWriter.STR: 369 // case ClassWriter.CLASS: 370 // case ClassWriter.MTYPE: 371 // case ClassWriter.MODULE: 372 // case ClassWriter.PACKAGE: 373 default: 374 item.set(tag, readUTF8(index, buf), null, null); 375 break; 376 } 377 378 int index2 = item.hashCode % items2.length; 379 item.next = items2[index2]; 380 items2[index2] = item; 381 } 382 383 int off = items[1] - 1; 384 classWriter.pool.putByteArray(b, off, header - off); 385 classWriter.items = items2; 386 classWriter.threshold = (int) (0.75d * ll); 387 classWriter.index = ll; 388 } 389 390 /** 391 * Copies the bootstrap method data into the given {@link ClassWriter}. 392 * Should be called before the {@link #accept(ClassVisitor,int)} method. 393 * 394 * @param classWriter 395 * the {@link ClassWriter} to copy bootstrap methods into. 396 */ 397 private void copyBootstrapMethods(final ClassWriter classWriter, 398 final Item[] items, final char[] c) { 399 // finds the "BootstrapMethods" attribute 400 int u = getAttributes(); 401 boolean found = false; 402 for (int i = readUnsignedShort(u); i > 0; --i) { 403 String attrName = readUTF8(u + 2, c); 404 if ("BootstrapMethods".equals(attrName)) { 405 found = true; 406 break; 407 } 408 u += 6 + readInt(u + 4); 409 } 410 if (!found) { 411 return; 412 } 413 // copies the bootstrap methods in the class writer 414 int boostrapMethodCount = readUnsignedShort(u + 8); 415 for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) { 416 int position = v - u - 10; 417 int hashCode = readConst(readUnsignedShort(v), c).hashCode(); 418 for (int k = readUnsignedShort(v + 2); k > 0; --k) { 419 hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode(); 420 v += 2; 421 } 422 v += 4; 423 Item item = new Item(j); 424 item.set(position, hashCode & 0x7FFFFFFF); 425 int index = item.hashCode % items.length; 426 item.next = items[index]; 427 items[index] = item; 428 } 429 int attrSize = readInt(u + 4); 430 ByteVector bootstrapMethods = new ByteVector(attrSize + 62); 431 bootstrapMethods.putByteArray(b, u + 10, attrSize - 2); 432 classWriter.bootstrapMethodsCount = boostrapMethodCount; 433 classWriter.bootstrapMethods = bootstrapMethods; 434 } 435 436 /** 437 * Constructs a new {@link ClassReader} object. 438 * 439 * @param is 440 * an input stream from which to read the class. 441 * @throws IOException 442 * if a problem occurs during reading. 443 */ 444 public ClassReader(final InputStream is) throws IOException { 445 this(readClass(is, false)); 446 } 447 448 /** 449 * Constructs a new {@link ClassReader} object. 450 * 451 * @param name 452 * the binary qualified name of the class to be read. 453 * @throws IOException 454 * if an exception occurs during reading. 455 */ 456 public ClassReader(final String name) throws IOException { 457 this(readClass( 458 ClassLoader.getSystemResourceAsStream(name.replace('.', '/') 459 + ".class"), true)); 460 } 461 462 /** 463 * Reads the bytecode of a class. 464 * 465 * @param is 466 * an input stream from which to read the class. 467 * @param close 468 * true to close the input stream after reading. 469 * @return the bytecode read from the given input stream. 470 * @throws IOException 471 * if a problem occurs during reading. 472 */ 473 private static byte[] readClass(final InputStream is, boolean close) 474 throws IOException { 475 if (is == null) { 476 throw new IOException("Class not found"); 477 } 478 try { 479 byte[] b = new byte[is.available()]; 480 int len = 0; 481 while (true) { 482 int n = is.read(b, len, b.length - len); 483 if (n == -1) { 484 if (len < b.length) { 485 byte[] c = new byte[len]; 486 System.arraycopy(b, 0, c, 0, len); 487 b = c; 488 } 489 return b; 490 } 491 len += n; 492 if (len == b.length) { 493 int last = is.read(); 494 if (last < 0) { 495 return b; 496 } 497 byte[] c = new byte[b.length + 1000]; 498 System.arraycopy(b, 0, c, 0, len); 499 c[len++] = (byte) last; 500 b = c; 501 } 502 } 503 } finally { 504 if (close) { 505 is.close(); 506 } 507 } 508 } 509 510 // ------------------------------------------------------------------------ 511 // Public methods 512 // ------------------------------------------------------------------------ 513 514 /** 515 * Makes the given visitor visit the Java class of this {@link ClassReader} 516 * . This class is the one specified in the constructor (see 517 * {@link #ClassReader(byte[]) ClassReader}). 518 * 519 * @param classVisitor 520 * the visitor that must visit this class. 521 * @param flags 522 * option flags that can be used to modify the default behavior 523 * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} 524 * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. 525 */ 526 public void accept(final ClassVisitor classVisitor, final int flags) { 527 accept(classVisitor, new Attribute[0], flags); 528 } 529 530 /** 531 * Makes the given visitor visit the Java class of this {@link ClassReader}. 532 * This class is the one specified in the constructor (see 533 * {@link #ClassReader(byte[]) ClassReader}). 534 * 535 * @param classVisitor 536 * the visitor that must visit this class. 537 * @param attrs 538 * prototypes of the attributes that must be parsed during the 539 * visit of the class. Any attribute whose type is not equal to 540 * the type of one the prototypes will not be parsed: its byte 541 * array value will be passed unchanged to the ClassWriter. 542 * <i>This may corrupt it if this value contains references to 543 * the constant pool, or has syntactic or semantic links with a 544 * class element that has been transformed by a class adapter 545 * between the reader and the writer</i>. 546 * @param flags 547 * option flags that can be used to modify the default behavior 548 * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} 549 * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. 550 */ 551 public void accept(final ClassVisitor classVisitor, 552 final Attribute[] attrs, final int flags) { 553 int u = header; // current offset in the class file 554 char[] c = new char[maxStringLength]; // buffer used to read strings 555 556 Context context = new Context(); 557 context.attrs = attrs; 558 context.flags = flags; 559 context.buffer = c; 560 561 // reads the class declaration 562 int access = readUnsignedShort(u); 563 String name = readClass(u + 2, c); 564 String superClass = readClass(u + 4, c); 565 String[] interfaces = new String[readUnsignedShort(u + 6)]; 566 u += 8; 567 for (int i = 0; i < interfaces.length; ++i) { 568 interfaces[i] = readClass(u, c); 569 u += 2; 570 } 571 572 // reads the class attributes 573 String signature = null; 574 String sourceFile = null; 575 String sourceDebug = null; 576 String enclosingOwner = null; 577 String enclosingName = null; 578 String enclosingDesc = null; 579 String moduleMainClass = null; 580 int anns = 0; 581 int ianns = 0; 582 int tanns = 0; 583 int itanns = 0; 584 int innerClasses = 0; 585 int module = 0; 586 int packages = 0; 587 Attribute attributes = null; 588 589 u = getAttributes(); 590 for (int i = readUnsignedShort(u); i > 0; --i) { 591 String attrName = readUTF8(u + 2, c); 592 // tests are sorted in decreasing frequency order 593 // (based on frequencies observed on typical classes) 594 if ("SourceFile".equals(attrName)) { 595 sourceFile = readUTF8(u + 8, c); 596 } else if ("InnerClasses".equals(attrName)) { 597 innerClasses = u + 8; 598 } else if ("EnclosingMethod".equals(attrName)) { 599 enclosingOwner = readClass(u + 8, c); 600 int item = readUnsignedShort(u + 10); 601 if (item != 0) { 602 enclosingName = readUTF8(items[item], c); 603 enclosingDesc = readUTF8(items[item] + 2, c); 604 } 605 } else if (SIGNATURES && "Signature".equals(attrName)) { 606 signature = readUTF8(u + 8, c); 607 } else if (ANNOTATIONS 608 && "RuntimeVisibleAnnotations".equals(attrName)) { 609 anns = u + 8; 610 } else if (ANNOTATIONS 611 && "RuntimeVisibleTypeAnnotations".equals(attrName)) { 612 tanns = u + 8; 613 } else if ("Deprecated".equals(attrName)) { 614 access |= Opcodes.ACC_DEPRECATED; 615 } else if ("Synthetic".equals(attrName)) { 616 access |= Opcodes.ACC_SYNTHETIC 617 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; 618 } else if ("SourceDebugExtension".equals(attrName)) { 619 int len = readInt(u + 4); 620 sourceDebug = readUTF(u + 8, len, new char[len]); 621 } else if (ANNOTATIONS 622 && "RuntimeInvisibleAnnotations".equals(attrName)) { 623 ianns = u + 8; 624 } else if (ANNOTATIONS 625 && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { 626 itanns = u + 8; 627 } else if ("Module".equals(attrName)) { 628 module = u + 8; 629 } else if ("ModuleMainClass".equals(attrName)) { 630 moduleMainClass = readClass(u + 8, c); 631 } else if ("ModulePackages".equals(attrName)) { 632 packages = u + 10; 633 } else if ("BootstrapMethods".equals(attrName)) { 634 int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; 635 for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { 636 bootstrapMethods[j] = v; 637 v += 2 + readUnsignedShort(v + 2) << 1; 638 } 639 context.bootstrapMethods = bootstrapMethods; 640 } else { 641 Attribute attr = readAttribute(attrs, attrName, u + 8, 642 readInt(u + 4), c, -1, null); 643 if (attr != null) { 644 attr.next = attributes; 645 attributes = attr; 646 } 647 } 648 u += 6 + readInt(u + 4); 649 } 650 651 // visits the class declaration 652 classVisitor.visit(readInt(items[1] - 7), access, name, signature, 653 superClass, interfaces); 654 655 // visits the source and debug info 656 if ((flags & SKIP_DEBUG) == 0 657 && (sourceFile != null || sourceDebug != null)) { 658 classVisitor.visitSource(sourceFile, sourceDebug); 659 } 660 661 // visits the module info and associated attributes 662 if (module != 0) { 663 readModule(classVisitor, context, module, 664 moduleMainClass, packages); 665 } 666 667 // visits the outer class 668 if (enclosingOwner != null) { 669 classVisitor.visitOuterClass(enclosingOwner, enclosingName, 670 enclosingDesc); 671 } 672 673 // visits the class annotations and type annotations 674 if (ANNOTATIONS && anns != 0) { 675 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { 676 v = readAnnotationValues(v + 2, c, true, 677 classVisitor.visitAnnotation(readUTF8(v, c), true)); 678 } 679 } 680 if (ANNOTATIONS && ianns != 0) { 681 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { 682 v = readAnnotationValues(v + 2, c, true, 683 classVisitor.visitAnnotation(readUTF8(v, c), false)); 684 } 685 } 686 if (ANNOTATIONS && tanns != 0) { 687 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { 688 v = readAnnotationTarget(context, v); 689 v = readAnnotationValues(v + 2, c, true, 690 classVisitor.visitTypeAnnotation(context.typeRef, 691 context.typePath, readUTF8(v, c), true)); 692 } 693 } 694 if (ANNOTATIONS && itanns != 0) { 695 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { 696 v = readAnnotationTarget(context, v); 697 v = readAnnotationValues(v + 2, c, true, 698 classVisitor.visitTypeAnnotation(context.typeRef, 699 context.typePath, readUTF8(v, c), false)); 700 } 701 } 702 703 // visits the attributes 704 while (attributes != null) { 705 Attribute attr = attributes.next; 706 attributes.next = null; 707 classVisitor.visitAttribute(attributes); 708 attributes = attr; 709 } 710 711 // visits the inner classes 712 if (innerClasses != 0) { 713 int v = innerClasses + 2; 714 for (int i = readUnsignedShort(innerClasses); i > 0; --i) { 715 classVisitor.visitInnerClass(readClass(v, c), 716 readClass(v + 2, c), readUTF8(v + 4, c), 717 readUnsignedShort(v + 6)); 718 v += 8; 719 } 720 } 721 722 // visits the fields and methods 723 u = header + 10 + 2 * interfaces.length; 724 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 725 u = readField(classVisitor, context, u); 726 } 727 u += 2; 728 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 729 u = readMethod(classVisitor, context, u); 730 } 731 732 // visits the end of the class 733 classVisitor.visitEnd(); 734 } 735 736 /** 737 * Reads the module attribute and visit it. 738 * 739 * @param classVisitor 740 * the current class visitor 741 * @param context 742 * information about the class being parsed. 743 * @param u 744 * start offset of the module attribute in the class file. 745 * @param mainClass 746 * name of the main class of a module or null. 747 * @param packages 748 * start offset of the concealed package attribute. 749 */ 750 private void readModule(final ClassVisitor classVisitor, 751 final Context context, int u, 752 final String mainClass, int packages) { 753 754 char[] buffer = context.buffer; 755 756 // reads module name, flags and version 757 String name = readModule(u, buffer); 758 int flags = readUnsignedShort(u + 2); 759 String version = readUTF8(u + 4, buffer); 760 u += 6; 761 762 ModuleVisitor mv = classVisitor.visitModule(name, flags, version); 763 if (mv == null) { 764 return; 765 } 766 767 // module attributes (main class, packages) 768 if (mainClass != null) { 769 mv.visitMainClass(mainClass); 770 } 771 772 if (packages != 0) { 773 for (int i = readUnsignedShort(packages - 2); i > 0; --i) { 774 String packaze = readPackage(packages, buffer); 775 mv.visitPackage(packaze); 776 packages += 2; 777 } 778 } 779 780 // reads requires 781 u += 2; 782 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 783 String module = readModule(u, buffer); 784 int access = readUnsignedShort(u + 2); 785 String requireVersion = readUTF8(u + 4, buffer); 786 mv.visitRequire(module, access, requireVersion); 787 u += 6; 788 } 789 790 // reads exports 791 u += 2; 792 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 793 String export = readPackage(u, buffer); 794 int access = readUnsignedShort(u + 2); 795 int exportToCount = readUnsignedShort(u + 4); 796 u += 6; 797 String[] tos = null; 798 if (exportToCount != 0) { 799 tos = new String[exportToCount]; 800 for (int j = 0; j < tos.length; ++j) { 801 tos[j] = readModule(u, buffer); 802 u += 2; 803 } 804 } 805 mv.visitExport(export, access, tos); 806 } 807 808 // reads opens 809 u += 2; 810 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 811 String open = readPackage(u, buffer); 812 int access = readUnsignedShort(u + 2); 813 int openToCount = readUnsignedShort(u + 4); 814 u += 6; 815 String[] tos = null; 816 if (openToCount != 0) { 817 tos = new String[openToCount]; 818 for (int j = 0; j < tos.length; ++j) { 819 tos[j] = readModule(u, buffer); 820 u += 2; 821 } 822 } 823 mv.visitOpen(open, access, tos); 824 } 825 826 // read uses 827 u += 2; 828 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 829 mv.visitUse(readClass(u, buffer)); 830 u += 2; 831 } 832 833 // read provides 834 u += 2; 835 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 836 String service = readClass(u, buffer); 837 int provideWithCount = readUnsignedShort(u + 2); 838 u += 4; 839 String[] withs = new String[provideWithCount]; 840 for (int j = 0; j < withs.length; ++j) { 841 withs[j] = readClass(u, buffer); 842 u += 2; 843 } 844 mv.visitProvide(service, withs); 845 } 846 847 mv.visitEnd(); 848 } 849 850 /** 851 * Reads a field and makes the given visitor visit it. 852 * 853 * @param classVisitor 854 * the visitor that must visit the field. 855 * @param context 856 * information about the class being parsed. 857 * @param u 858 * the start offset of the field in the class file. 859 * @return the offset of the first byte following the field in the class. 860 */ 861 private int readField(final ClassVisitor classVisitor, 862 final Context context, int u) { 863 // reads the field declaration 864 char[] c = context.buffer; 865 int access = readUnsignedShort(u); 866 String name = readUTF8(u + 2, c); 867 String desc = readUTF8(u + 4, c); 868 u += 6; 869 870 // reads the field attributes 871 String signature = null; 872 int anns = 0; 873 int ianns = 0; 874 int tanns = 0; 875 int itanns = 0; 876 Object value = null; 877 Attribute attributes = null; 878 879 for (int i = readUnsignedShort(u); i > 0; --i) { 880 String attrName = readUTF8(u + 2, c); 881 // tests are sorted in decreasing frequency order 882 // (based on frequencies observed on typical classes) 883 if ("ConstantValue".equals(attrName)) { 884 int item = readUnsignedShort(u + 8); 885 value = item == 0 ? null : readConst(item, c); 886 } else if (SIGNATURES && "Signature".equals(attrName)) { 887 signature = readUTF8(u + 8, c); 888 } else if ("Deprecated".equals(attrName)) { 889 access |= Opcodes.ACC_DEPRECATED; 890 } else if ("Synthetic".equals(attrName)) { 891 access |= Opcodes.ACC_SYNTHETIC 892 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; 893 } else if (ANNOTATIONS 894 && "RuntimeVisibleAnnotations".equals(attrName)) { 895 anns = u + 8; 896 } else if (ANNOTATIONS 897 && "RuntimeVisibleTypeAnnotations".equals(attrName)) { 898 tanns = u + 8; 899 } else if (ANNOTATIONS 900 && "RuntimeInvisibleAnnotations".equals(attrName)) { 901 ianns = u + 8; 902 } else if (ANNOTATIONS 903 && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { 904 itanns = u + 8; 905 } else { 906 Attribute attr = readAttribute(context.attrs, attrName, u + 8, 907 readInt(u + 4), c, -1, null); 908 if (attr != null) { 909 attr.next = attributes; 910 attributes = attr; 911 } 912 } 913 u += 6 + readInt(u + 4); 914 } 915 u += 2; 916 917 // visits the field declaration 918 FieldVisitor fv = classVisitor.visitField(access, name, desc, 919 signature, value); 920 if (fv == null) { 921 return u; 922 } 923 924 // visits the field annotations and type annotations 925 if (ANNOTATIONS && anns != 0) { 926 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { 927 v = readAnnotationValues(v + 2, c, true, 928 fv.visitAnnotation(readUTF8(v, c), true)); 929 } 930 } 931 if (ANNOTATIONS && ianns != 0) { 932 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { 933 v = readAnnotationValues(v + 2, c, true, 934 fv.visitAnnotation(readUTF8(v, c), false)); 935 } 936 } 937 if (ANNOTATIONS && tanns != 0) { 938 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { 939 v = readAnnotationTarget(context, v); 940 v = readAnnotationValues(v + 2, c, true, 941 fv.visitTypeAnnotation(context.typeRef, 942 context.typePath, readUTF8(v, c), true)); 943 } 944 } 945 if (ANNOTATIONS && itanns != 0) { 946 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { 947 v = readAnnotationTarget(context, v); 948 v = readAnnotationValues(v + 2, c, true, 949 fv.visitTypeAnnotation(context.typeRef, 950 context.typePath, readUTF8(v, c), false)); 951 } 952 } 953 954 // visits the field attributes 955 while (attributes != null) { 956 Attribute attr = attributes.next; 957 attributes.next = null; 958 fv.visitAttribute(attributes); 959 attributes = attr; 960 } 961 962 // visits the end of the field 963 fv.visitEnd(); 964 965 return u; 966 } 967 968 /** 969 * Reads a method and makes the given visitor visit it. 970 * 971 * @param classVisitor 972 * the visitor that must visit the method. 973 * @param context 974 * information about the class being parsed. 975 * @param u 976 * the start offset of the method in the class file. 977 * @return the offset of the first byte following the method in the class. 978 */ 979 private int readMethod(final ClassVisitor classVisitor, 980 final Context context, int u) { 981 // reads the method declaration 982 char[] c = context.buffer; 983 context.access = readUnsignedShort(u); 984 context.name = readUTF8(u + 2, c); 985 context.desc = readUTF8(u + 4, c); 986 u += 6; 987 988 // reads the method attributes 989 int code = 0; 990 int exception = 0; 991 String[] exceptions = null; 992 String signature = null; 993 int methodParameters = 0; 994 int anns = 0; 995 int ianns = 0; 996 int tanns = 0; 997 int itanns = 0; 998 int dann = 0; 999 int mpanns = 0; 1000 int impanns = 0; 1001 int firstAttribute = u; 1002 Attribute attributes = null; 1003 1004 for (int i = readUnsignedShort(u); i > 0; --i) { 1005 String attrName = readUTF8(u + 2, c); 1006 // tests are sorted in decreasing frequency order 1007 // (based on frequencies observed on typical classes) 1008 if ("Code".equals(attrName)) { 1009 if ((context.flags & SKIP_CODE) == 0) { 1010 code = u + 8; 1011 } 1012 } else if ("Exceptions".equals(attrName)) { 1013 exceptions = new String[readUnsignedShort(u + 8)]; 1014 exception = u + 10; 1015 for (int j = 0; j < exceptions.length; ++j) { 1016 exceptions[j] = readClass(exception, c); 1017 exception += 2; 1018 } 1019 } else if (SIGNATURES && "Signature".equals(attrName)) { 1020 signature = readUTF8(u + 8, c); 1021 } else if ("Deprecated".equals(attrName)) { 1022 context.access |= Opcodes.ACC_DEPRECATED; 1023 } else if (ANNOTATIONS 1024 && "RuntimeVisibleAnnotations".equals(attrName)) { 1025 anns = u + 8; 1026 } else if (ANNOTATIONS 1027 && "RuntimeVisibleTypeAnnotations".equals(attrName)) { 1028 tanns = u + 8; 1029 } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { 1030 dann = u + 8; 1031 } else if ("Synthetic".equals(attrName)) { 1032 context.access |= Opcodes.ACC_SYNTHETIC 1033 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; 1034 } else if (ANNOTATIONS 1035 && "RuntimeInvisibleAnnotations".equals(attrName)) { 1036 ianns = u + 8; 1037 } else if (ANNOTATIONS 1038 && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { 1039 itanns = u + 8; 1040 } else if (ANNOTATIONS 1041 && "RuntimeVisibleParameterAnnotations".equals(attrName)) { 1042 mpanns = u + 8; 1043 } else if (ANNOTATIONS 1044 && "RuntimeInvisibleParameterAnnotations".equals(attrName)) { 1045 impanns = u + 8; 1046 } else if ("MethodParameters".equals(attrName)) { 1047 methodParameters = u + 8; 1048 } else { 1049 Attribute attr = readAttribute(context.attrs, attrName, u + 8, 1050 readInt(u + 4), c, -1, null); 1051 if (attr != null) { 1052 attr.next = attributes; 1053 attributes = attr; 1054 } 1055 } 1056 u += 6 + readInt(u + 4); 1057 } 1058 u += 2; 1059 1060 // visits the method declaration 1061 MethodVisitor mv = classVisitor.visitMethod(context.access, 1062 context.name, context.desc, signature, exceptions); 1063 if (mv == null) { 1064 return u; 1065 } 1066 1067 /* 1068 * if the returned MethodVisitor is in fact a MethodWriter, it means 1069 * there is no method adapter between the reader and the writer. If, in 1070 * addition, the writer's constant pool was copied from this reader 1071 * (mw.cw.cr == this), and the signature and exceptions of the method 1072 * have not been changed, then it is possible to skip all visit events 1073 * and just copy the original code of the method to the writer (the 1074 * access, name and descriptor can have been changed, this is not 1075 * important since they are not copied as is from the reader). 1076 */ 1077 if (WRITER && mv instanceof MethodWriter) { 1078 MethodWriter mw = (MethodWriter) mv; 1079 if (mw.cw.cr == this && 1080 (signature != null ? signature.equals(mw.signature) : mw.signature == null)) { 1081 boolean sameExceptions = false; 1082 if (exceptions == null) { 1083 sameExceptions = mw.exceptionCount == 0; 1084 } else if (exceptions.length == mw.exceptionCount) { 1085 sameExceptions = true; 1086 for (int j = exceptions.length - 1; j >= 0; --j) { 1087 exception -= 2; 1088 if (mw.exceptions[j] != readUnsignedShort(exception)) { 1089 sameExceptions = false; 1090 break; 1091 } 1092 } 1093 } 1094 if (sameExceptions) { 1095 /* 1096 * we do not copy directly the code into MethodWriter to 1097 * save a byte array copy operation. The real copy will be 1098 * done in ClassWriter.toByteArray(). 1099 */ 1100 mw.classReaderOffset = firstAttribute; 1101 mw.classReaderLength = u - firstAttribute; 1102 return u; 1103 } 1104 } 1105 } 1106 1107 // visit the method parameters 1108 if (methodParameters != 0) { 1109 for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) { 1110 mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2)); 1111 } 1112 } 1113 1114 // visits the method annotations 1115 if (ANNOTATIONS && dann != 0) { 1116 AnnotationVisitor dv = mv.visitAnnotationDefault(); 1117 readAnnotationValue(dann, c, null, dv); 1118 if (dv != null) { 1119 dv.visitEnd(); 1120 } 1121 } 1122 if (ANNOTATIONS && anns != 0) { 1123 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { 1124 v = readAnnotationValues(v + 2, c, true, 1125 mv.visitAnnotation(readUTF8(v, c), true)); 1126 } 1127 } 1128 if (ANNOTATIONS && ianns != 0) { 1129 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { 1130 v = readAnnotationValues(v + 2, c, true, 1131 mv.visitAnnotation(readUTF8(v, c), false)); 1132 } 1133 } 1134 if (ANNOTATIONS && tanns != 0) { 1135 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { 1136 v = readAnnotationTarget(context, v); 1137 v = readAnnotationValues(v + 2, c, true, 1138 mv.visitTypeAnnotation(context.typeRef, 1139 context.typePath, readUTF8(v, c), true)); 1140 } 1141 } 1142 if (ANNOTATIONS && itanns != 0) { 1143 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { 1144 v = readAnnotationTarget(context, v); 1145 v = readAnnotationValues(v + 2, c, true, 1146 mv.visitTypeAnnotation(context.typeRef, 1147 context.typePath, readUTF8(v, c), false)); 1148 } 1149 } 1150 if (ANNOTATIONS && mpanns != 0) { 1151 readParameterAnnotations(mv, context, mpanns, true); 1152 } 1153 if (ANNOTATIONS && impanns != 0) { 1154 readParameterAnnotations(mv, context, impanns, false); 1155 } 1156 1157 // visits the method attributes 1158 while (attributes != null) { 1159 Attribute attr = attributes.next; 1160 attributes.next = null; 1161 mv.visitAttribute(attributes); 1162 attributes = attr; 1163 } 1164 1165 // visits the method code 1166 if (code != 0) { 1167 mv.visitCode(); 1168 readCode(mv, context, code); 1169 } 1170 1171 // visits the end of the method 1172 mv.visitEnd(); 1173 1174 return u; 1175 } 1176 1177 /** 1178 * Reads the bytecode of a method and makes the given visitor visit it. 1179 * 1180 * @param mv 1181 * the visitor that must visit the method's code. 1182 * @param context 1183 * information about the class being parsed. 1184 * @param u 1185 * the start offset of the code attribute in the class file. 1186 */ 1187 private void readCode(final MethodVisitor mv, final Context context, int u) { 1188 // reads the header 1189 byte[] b = this.b; 1190 char[] c = context.buffer; 1191 int maxStack = readUnsignedShort(u); 1192 int maxLocals = readUnsignedShort(u + 2); 1193 int codeLength = readInt(u + 4); 1194 u += 8; 1195 1196 // reads the bytecode to find the labels 1197 int codeStart = u; 1198 int codeEnd = u + codeLength; 1199 Label[] labels = context.labels = new Label[codeLength + 2]; 1200 readLabel(codeLength + 1, labels); 1201 while (u < codeEnd) { 1202 int offset = u - codeStart; 1203 int opcode = b[u] & 0xFF; 1204 switch (ClassWriter.TYPE[opcode]) { 1205 case ClassWriter.NOARG_INSN: 1206 case ClassWriter.IMPLVAR_INSN: 1207 u += 1; 1208 break; 1209 case ClassWriter.LABEL_INSN: 1210 readLabel(offset + readShort(u + 1), labels); 1211 u += 3; 1212 break; 1213 case ClassWriter.ASM_LABEL_INSN: 1214 readLabel(offset + readUnsignedShort(u + 1), labels); 1215 u += 3; 1216 break; 1217 case ClassWriter.LABELW_INSN: 1218 case ClassWriter.ASM_LABELW_INSN: 1219 readLabel(offset + readInt(u + 1), labels); 1220 u += 5; 1221 break; 1222 case ClassWriter.WIDE_INSN: 1223 opcode = b[u + 1] & 0xFF; 1224 if (opcode == Opcodes.IINC) { 1225 u += 6; 1226 } else { 1227 u += 4; 1228 } 1229 break; 1230 case ClassWriter.TABL_INSN: 1231 // skips 0 to 3 padding bytes 1232 u = u + 4 - (offset & 3); 1233 // reads instruction 1234 readLabel(offset + readInt(u), labels); 1235 for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { 1236 readLabel(offset + readInt(u + 12), labels); 1237 u += 4; 1238 } 1239 u += 12; 1240 break; 1241 case ClassWriter.LOOK_INSN: 1242 // skips 0 to 3 padding bytes 1243 u = u + 4 - (offset & 3); 1244 // reads instruction 1245 readLabel(offset + readInt(u), labels); 1246 for (int i = readInt(u + 4); i > 0; --i) { 1247 readLabel(offset + readInt(u + 12), labels); 1248 u += 8; 1249 } 1250 u += 8; 1251 break; 1252 case ClassWriter.VAR_INSN: 1253 case ClassWriter.SBYTE_INSN: 1254 case ClassWriter.LDC_INSN: 1255 u += 2; 1256 break; 1257 case ClassWriter.SHORT_INSN: 1258 case ClassWriter.LDCW_INSN: 1259 case ClassWriter.FIELDORMETH_INSN: 1260 case ClassWriter.TYPE_INSN: 1261 case ClassWriter.IINC_INSN: 1262 u += 3; 1263 break; 1264 case ClassWriter.ITFMETH_INSN: 1265 case ClassWriter.INDYMETH_INSN: 1266 u += 5; 1267 break; 1268 // case MANA_INSN: 1269 default: 1270 u += 4; 1271 break; 1272 } 1273 } 1274 1275 // reads the try catch entries to find the labels, and also visits them 1276 for (int i = readUnsignedShort(u); i > 0; --i) { 1277 Label start = readLabel(readUnsignedShort(u + 2), labels); 1278 Label end = readLabel(readUnsignedShort(u + 4), labels); 1279 Label handler = readLabel(readUnsignedShort(u + 6), labels); 1280 String type = readUTF8(items[readUnsignedShort(u + 8)], c); 1281 mv.visitTryCatchBlock(start, end, handler, type); 1282 u += 8; 1283 } 1284 u += 2; 1285 1286 // reads the code attributes 1287 int[] tanns = null; // start index of each visible type annotation 1288 int[] itanns = null; // start index of each invisible type annotation 1289 int tann = 0; // current index in tanns array 1290 int itann = 0; // current index in itanns array 1291 int ntoff = -1; // next visible type annotation code offset 1292 int nitoff = -1; // next invisible type annotation code offset 1293 int varTable = 0; 1294 int varTypeTable = 0; 1295 boolean zip = true; 1296 boolean unzip = (context.flags & EXPAND_FRAMES) != 0; 1297 int stackMap = 0; 1298 int stackMapSize = 0; 1299 int frameCount = 0; 1300 Context frame = null; 1301 Attribute attributes = null; 1302 1303 for (int i = readUnsignedShort(u); i > 0; --i) { 1304 String attrName = readUTF8(u + 2, c); 1305 if ("LocalVariableTable".equals(attrName)) { 1306 if ((context.flags & SKIP_DEBUG) == 0) { 1307 varTable = u + 8; 1308 for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { 1309 int label = readUnsignedShort(v + 10); 1310 if (labels[label] == null) { 1311 readLabel(label, labels).status |= Label.DEBUG; 1312 } 1313 label += readUnsignedShort(v + 12); 1314 if (labels[label] == null) { 1315 readLabel(label, labels).status |= Label.DEBUG; 1316 } 1317 v += 10; 1318 } 1319 } 1320 } else if ("LocalVariableTypeTable".equals(attrName)) { 1321 varTypeTable = u + 8; 1322 } else if ("LineNumberTable".equals(attrName)) { 1323 if ((context.flags & SKIP_DEBUG) == 0) { 1324 for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { 1325 int label = readUnsignedShort(v + 10); 1326 if (labels[label] == null) { 1327 readLabel(label, labels).status |= Label.DEBUG; 1328 } 1329 Label l = labels[label]; 1330 while (l.line > 0) { 1331 if (l.next == null) { 1332 l.next = new Label(); 1333 } 1334 l = l.next; 1335 } 1336 l.line = readUnsignedShort(v + 12); 1337 v += 4; 1338 } 1339 } 1340 } else if (ANNOTATIONS 1341 && "RuntimeVisibleTypeAnnotations".equals(attrName)) { 1342 tanns = readTypeAnnotations(mv, context, u + 8, true); 1343 ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 1344 : readUnsignedShort(tanns[0] + 1); 1345 } else if (ANNOTATIONS 1346 && "RuntimeInvisibleTypeAnnotations".equals(attrName)) { 1347 itanns = readTypeAnnotations(mv, context, u + 8, false); 1348 nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 1349 : readUnsignedShort(itanns[0] + 1); 1350 } else if (FRAMES && "StackMapTable".equals(attrName)) { 1351 if ((context.flags & SKIP_FRAMES) == 0) { 1352 stackMap = u + 10; 1353 stackMapSize = readInt(u + 4); 1354 frameCount = readUnsignedShort(u + 8); 1355 } 1356 /* 1357 * here we do not extract the labels corresponding to the 1358 * attribute content. This would require a full parsing of the 1359 * attribute, which would need to be repeated in the second 1360 * phase (see below). Instead the content of the attribute is 1361 * read one frame at a time (i.e. after a frame has been 1362 * visited, the next frame is read), and the labels it contains 1363 * are also extracted one frame at a time. Thanks to the 1364 * ordering of frames, having only a "one frame lookahead" is 1365 * not a problem, i.e. it is not possible to see an offset 1366 * smaller than the offset of the current insn and for which no 1367 * Label exist. 1368 */ 1369 /* 1370 * This is not true for UNINITIALIZED type offsets. We solve 1371 * this by parsing the stack map table without a full decoding 1372 * (see below). 1373 */ 1374 } else if (FRAMES && "StackMap".equals(attrName)) { 1375 if ((context.flags & SKIP_FRAMES) == 0) { 1376 zip = false; 1377 stackMap = u + 10; 1378 stackMapSize = readInt(u + 4); 1379 frameCount = readUnsignedShort(u + 8); 1380 } 1381 /* 1382 * IMPORTANT! here we assume that the frames are ordered, as in 1383 * the StackMapTable attribute, although this is not guaranteed 1384 * by the attribute format. 1385 */ 1386 } else { 1387 for (int j = 0; j < context.attrs.length; ++j) { 1388 if (context.attrs[j].type.equals(attrName)) { 1389 Attribute attr = context.attrs[j].read(this, u + 8, 1390 readInt(u + 4), c, codeStart - 8, labels); 1391 if (attr != null) { 1392 attr.next = attributes; 1393 attributes = attr; 1394 } 1395 } 1396 } 1397 } 1398 u += 6 + readInt(u + 4); 1399 } 1400 u += 2; 1401 1402 // generates the first (implicit) stack map frame 1403 if (FRAMES && stackMap != 0) { 1404 /* 1405 * for the first explicit frame the offset is not offset_delta + 1 1406 * but only offset_delta; setting the implicit frame offset to -1 1407 * allow the use of the "offset_delta + 1" rule in all cases 1408 */ 1409 frame = context; 1410 frame.offset = -1; 1411 frame.mode = 0; 1412 frame.localCount = 0; 1413 frame.localDiff = 0; 1414 frame.stackCount = 0; 1415 frame.local = new Object[maxLocals]; 1416 frame.stack = new Object[maxStack]; 1417 if (unzip) { 1418 getImplicitFrame(context); 1419 } 1420 /* 1421 * Finds labels for UNINITIALIZED frame types. Instead of decoding 1422 * each element of the stack map table, we look for 3 consecutive 1423 * bytes that "look like" an UNINITIALIZED type (tag 8, offset 1424 * within code bounds, NEW instruction at this offset). We may find 1425 * false positives (i.e. not real UNINITIALIZED types), but this 1426 * should be rare, and the only consequence will be the creation of 1427 * an unneeded label. This is better than creating a label for each 1428 * NEW instruction, and faster than fully decoding the whole stack 1429 * map table. 1430 */ 1431 for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) { 1432 if (b[i] == 8) { // UNINITIALIZED FRAME TYPE 1433 int v = readUnsignedShort(i + 1); 1434 if (v >= 0 && v < codeLength) { 1435 if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { 1436 readLabel(v, labels); 1437 } 1438 } 1439 } 1440 } 1441 } 1442 if ((context.flags & EXPAND_ASM_INSNS) != 0 1443 && (context.flags & EXPAND_FRAMES) != 0) { 1444 // Expanding the ASM pseudo instructions can introduce F_INSERT 1445 // frames, even if the method does not currently have any frame. 1446 // Also these inserted frames must be computed by simulating the 1447 // effect of the bytecode instructions one by one, starting from the 1448 // first one and the last existing frame (or the implicit first 1449 // one). Finally, due to the way MethodWriter computes this (with 1450 // the compute = INSERTED_FRAMES option), MethodWriter needs to know 1451 // maxLocals before the first instruction is visited. For all these 1452 // reasons we always visit the implicit first frame in this case 1453 // (passing only maxLocals - the rest can be and is computed in 1454 // MethodWriter). 1455 mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null); 1456 } 1457 1458 // visits the instructions 1459 int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0; 1460 boolean insertFrame = false; 1461 u = codeStart; 1462 while (u < codeEnd) { 1463 int offset = u - codeStart; 1464 1465 // visits the label and line number for this offset, if any 1466 Label l = labels[offset]; 1467 if (l != null) { 1468 Label next = l.next; 1469 l.next = null; 1470 mv.visitLabel(l); 1471 if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { 1472 mv.visitLineNumber(l.line, l); 1473 while (next != null) { 1474 mv.visitLineNumber(next.line, l); 1475 next = next.next; 1476 } 1477 } 1478 } 1479 1480 // visits the frame for this offset, if any 1481 while (FRAMES && frame != null 1482 && (frame.offset == offset || frame.offset == -1)) { 1483 // if there is a frame for this offset, makes the visitor visit 1484 // it, and reads the next frame if there is one. 1485 if (frame.offset != -1) { 1486 if (!zip || unzip) { 1487 mv.visitFrame(Opcodes.F_NEW, frame.localCount, 1488 frame.local, frame.stackCount, frame.stack); 1489 } else { 1490 mv.visitFrame(frame.mode, frame.localDiff, frame.local, 1491 frame.stackCount, frame.stack); 1492 } 1493 // if there is already a frame for this offset, there is no 1494 // need to insert a new one. 1495 insertFrame = false; 1496 } 1497 if (frameCount > 0) { 1498 stackMap = readFrame(stackMap, zip, unzip, frame); 1499 --frameCount; 1500 } else { 1501 frame = null; 1502 } 1503 } 1504 // inserts a frame for this offset, if requested by setting 1505 // insertFrame to true during the previous iteration. The actual 1506 // frame content will be computed in MethodWriter. 1507 if (FRAMES && insertFrame) { 1508 mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null); 1509 insertFrame = false; 1510 } 1511 1512 // visits the instruction at this offset 1513 int opcode = b[u] & 0xFF; 1514 switch (ClassWriter.TYPE[opcode]) { 1515 case ClassWriter.NOARG_INSN: 1516 mv.visitInsn(opcode); 1517 u += 1; 1518 break; 1519 case ClassWriter.IMPLVAR_INSN: 1520 if (opcode > Opcodes.ISTORE) { 1521 opcode -= 59; // ISTORE_0 1522 mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), 1523 opcode & 0x3); 1524 } else { 1525 opcode -= 26; // ILOAD_0 1526 mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3); 1527 } 1528 u += 1; 1529 break; 1530 case ClassWriter.LABEL_INSN: 1531 mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]); 1532 u += 3; 1533 break; 1534 case ClassWriter.LABELW_INSN: 1535 mv.visitJumpInsn(opcode + opcodeDelta, labels[offset 1536 + readInt(u + 1)]); 1537 u += 5; 1538 break; 1539 case ClassWriter.ASM_LABEL_INSN: { 1540 // changes temporary opcodes 202 to 217 (inclusive), 218 1541 // and 219 to IFEQ ... JSR (inclusive), IFNULL and 1542 // IFNONNULL 1543 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1544 Label target = labels[offset + readUnsignedShort(u + 1)]; 1545 // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx 1546 // <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is 1547 // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) 1548 // and where <L> designates the instruction just after 1549 // the GOTO_W. 1550 if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { 1551 mv.visitJumpInsn(opcode + 33, target); 1552 } else { 1553 opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1 1554 : opcode ^ 1; 1555 Label endif = readLabel(offset + 3, labels); 1556 mv.visitJumpInsn(opcode, endif); 1557 mv.visitJumpInsn(200, target); // GOTO_W 1558 // endif designates the instruction just after GOTO_W, 1559 // and is visited as part of the next instruction. Since 1560 // it is a jump target, we need to insert a frame here. 1561 insertFrame = true; 1562 } 1563 u += 3; 1564 break; 1565 } 1566 case ClassWriter.ASM_LABELW_INSN: { 1567 // replaces the pseudo GOTO_W instruction with a real one. 1568 mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]); 1569 // The instruction just after is a jump target (because pseudo 1570 // GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:..., 1571 // see MethodWriter), so we need to insert a frame here. 1572 insertFrame = true; 1573 u += 5; 1574 break; 1575 } 1576 case ClassWriter.WIDE_INSN: 1577 opcode = b[u + 1] & 0xFF; 1578 if (opcode == Opcodes.IINC) { 1579 mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4)); 1580 u += 6; 1581 } else { 1582 mv.visitVarInsn(opcode, readUnsignedShort(u + 2)); 1583 u += 4; 1584 } 1585 break; 1586 case ClassWriter.TABL_INSN: { 1587 // skips 0 to 3 padding bytes 1588 u = u + 4 - (offset & 3); 1589 // reads instruction 1590 int label = offset + readInt(u); 1591 int min = readInt(u + 4); 1592 int max = readInt(u + 8); 1593 Label[] table = new Label[max - min + 1]; 1594 u += 12; 1595 for (int i = 0; i < table.length; ++i) { 1596 table[i] = labels[offset + readInt(u)]; 1597 u += 4; 1598 } 1599 mv.visitTableSwitchInsn(min, max, labels[label], table); 1600 break; 1601 } 1602 case ClassWriter.LOOK_INSN: { 1603 // skips 0 to 3 padding bytes 1604 u = u + 4 - (offset & 3); 1605 // reads instruction 1606 int label = offset + readInt(u); 1607 int len = readInt(u + 4); 1608 int[] keys = new int[len]; 1609 Label[] values = new Label[len]; 1610 u += 8; 1611 for (int i = 0; i < len; ++i) { 1612 keys[i] = readInt(u); 1613 values[i] = labels[offset + readInt(u + 4)]; 1614 u += 8; 1615 } 1616 mv.visitLookupSwitchInsn(labels[label], keys, values); 1617 break; 1618 } 1619 case ClassWriter.VAR_INSN: 1620 mv.visitVarInsn(opcode, b[u + 1] & 0xFF); 1621 u += 2; 1622 break; 1623 case ClassWriter.SBYTE_INSN: 1624 mv.visitIntInsn(opcode, b[u + 1]); 1625 u += 2; 1626 break; 1627 case ClassWriter.SHORT_INSN: 1628 mv.visitIntInsn(opcode, readShort(u + 1)); 1629 u += 3; 1630 break; 1631 case ClassWriter.LDC_INSN: 1632 mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c)); 1633 u += 2; 1634 break; 1635 case ClassWriter.LDCW_INSN: 1636 mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c)); 1637 u += 3; 1638 break; 1639 case ClassWriter.FIELDORMETH_INSN: 1640 case ClassWriter.ITFMETH_INSN: { 1641 int cpIndex = items[readUnsignedShort(u + 1)]; 1642 boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; 1643 String iowner = readClass(cpIndex, c); 1644 cpIndex = items[readUnsignedShort(cpIndex + 2)]; 1645 String iname = readUTF8(cpIndex, c); 1646 String idesc = readUTF8(cpIndex + 2, c); 1647 if (opcode < Opcodes.INVOKEVIRTUAL) { 1648 mv.visitFieldInsn(opcode, iowner, iname, idesc); 1649 } else { 1650 mv.visitMethodInsn(opcode, iowner, iname, idesc, itf); 1651 } 1652 if (opcode == Opcodes.INVOKEINTERFACE) { 1653 u += 5; 1654 } else { 1655 u += 3; 1656 } 1657 break; 1658 } 1659 case ClassWriter.INDYMETH_INSN: { 1660 int cpIndex = items[readUnsignedShort(u + 1)]; 1661 int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)]; 1662 Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c); 1663 int bsmArgCount = readUnsignedShort(bsmIndex + 2); 1664 Object[] bsmArgs = new Object[bsmArgCount]; 1665 bsmIndex += 4; 1666 for (int i = 0; i < bsmArgCount; i++) { 1667 bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c); 1668 bsmIndex += 2; 1669 } 1670 cpIndex = items[readUnsignedShort(cpIndex + 2)]; 1671 String iname = readUTF8(cpIndex, c); 1672 String idesc = readUTF8(cpIndex + 2, c); 1673 mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs); 1674 u += 5; 1675 break; 1676 } 1677 case ClassWriter.TYPE_INSN: 1678 mv.visitTypeInsn(opcode, readClass(u + 1, c)); 1679 u += 3; 1680 break; 1681 case ClassWriter.IINC_INSN: 1682 mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]); 1683 u += 3; 1684 break; 1685 // case MANA_INSN: 1686 default: 1687 mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF); 1688 u += 4; 1689 break; 1690 } 1691 1692 // visit the instruction annotations, if any 1693 while (tanns != null && tann < tanns.length && ntoff <= offset) { 1694 if (ntoff == offset) { 1695 int v = readAnnotationTarget(context, tanns[tann]); 1696 readAnnotationValues(v + 2, c, true, 1697 mv.visitInsnAnnotation(context.typeRef, 1698 context.typePath, readUTF8(v, c), true)); 1699 } 1700 ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1 1701 : readUnsignedShort(tanns[tann] + 1); 1702 } 1703 while (itanns != null && itann < itanns.length && nitoff <= offset) { 1704 if (nitoff == offset) { 1705 int v = readAnnotationTarget(context, itanns[itann]); 1706 readAnnotationValues(v + 2, c, true, 1707 mv.visitInsnAnnotation(context.typeRef, 1708 context.typePath, readUTF8(v, c), false)); 1709 } 1710 nitoff = ++itann >= itanns.length 1711 || readByte(itanns[itann]) < 0x43 ? -1 1712 : readUnsignedShort(itanns[itann] + 1); 1713 } 1714 } 1715 if (labels[codeLength] != null) { 1716 mv.visitLabel(labels[codeLength]); 1717 } 1718 1719 // visits the local variable tables 1720 if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) { 1721 int[] typeTable = null; 1722 if (varTypeTable != 0) { 1723 u = varTypeTable + 2; 1724 typeTable = new int[readUnsignedShort(varTypeTable) * 3]; 1725 for (int i = typeTable.length; i > 0;) { 1726 typeTable[--i] = u + 6; // signature 1727 typeTable[--i] = readUnsignedShort(u + 8); // index 1728 typeTable[--i] = readUnsignedShort(u); // start 1729 u += 10; 1730 } 1731 } 1732 u = varTable + 2; 1733 for (int i = readUnsignedShort(varTable); i > 0; --i) { 1734 int start = readUnsignedShort(u); 1735 int length = readUnsignedShort(u + 2); 1736 int index = readUnsignedShort(u + 8); 1737 String vsignature = null; 1738 if (typeTable != null) { 1739 for (int j = 0; j < typeTable.length; j += 3) { 1740 if (typeTable[j] == start && typeTable[j + 1] == index) { 1741 vsignature = readUTF8(typeTable[j + 2], c); 1742 break; 1743 } 1744 } 1745 } 1746 mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), 1747 vsignature, labels[start], labels[start + length], 1748 index); 1749 u += 10; 1750 } 1751 } 1752 1753 // visits the local variables type annotations 1754 if (tanns != null) { 1755 for (int i = 0; i < tanns.length; ++i) { 1756 if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) { 1757 int v = readAnnotationTarget(context, tanns[i]); 1758 v = readAnnotationValues(v + 2, c, true, 1759 mv.visitLocalVariableAnnotation(context.typeRef, 1760 context.typePath, context.start, 1761 context.end, context.index, readUTF8(v, c), 1762 true)); 1763 } 1764 } 1765 } 1766 if (itanns != null) { 1767 for (int i = 0; i < itanns.length; ++i) { 1768 if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) { 1769 int v = readAnnotationTarget(context, itanns[i]); 1770 v = readAnnotationValues(v + 2, c, true, 1771 mv.visitLocalVariableAnnotation(context.typeRef, 1772 context.typePath, context.start, 1773 context.end, context.index, readUTF8(v, c), 1774 false)); 1775 } 1776 } 1777 } 1778 1779 // visits the code attributes 1780 while (attributes != null) { 1781 Attribute attr = attributes.next; 1782 attributes.next = null; 1783 mv.visitAttribute(attributes); 1784 attributes = attr; 1785 } 1786 1787 // visits the max stack and max locals values 1788 mv.visitMaxs(maxStack, maxLocals); 1789 } 1790 1791 /** 1792 * Parses a type annotation table to find the labels, and to visit the try 1793 * catch block annotations. 1794 * 1795 * @param u 1796 * the start offset of a type annotation table. 1797 * @param mv 1798 * the method visitor to be used to visit the try catch block 1799 * annotations. 1800 * @param context 1801 * information about the class being parsed. 1802 * @param visible 1803 * if the type annotation table to parse contains runtime visible 1804 * annotations. 1805 * @return the start offset of each type annotation in the parsed table. 1806 */ 1807 private int[] readTypeAnnotations(final MethodVisitor mv, 1808 final Context context, int u, boolean visible) { 1809 char[] c = context.buffer; 1810 int[] offsets = new int[readUnsignedShort(u)]; 1811 u += 2; 1812 for (int i = 0; i < offsets.length; ++i) { 1813 offsets[i] = u; 1814 int target = readInt(u); 1815 switch (target >>> 24) { 1816 case 0x00: // CLASS_TYPE_PARAMETER 1817 case 0x01: // METHOD_TYPE_PARAMETER 1818 case 0x16: // METHOD_FORMAL_PARAMETER 1819 u += 2; 1820 break; 1821 case 0x13: // FIELD 1822 case 0x14: // METHOD_RETURN 1823 case 0x15: // METHOD_RECEIVER 1824 u += 1; 1825 break; 1826 case 0x40: // LOCAL_VARIABLE 1827 case 0x41: // RESOURCE_VARIABLE 1828 for (int j = readUnsignedShort(u + 1); j > 0; --j) { 1829 int start = readUnsignedShort(u + 3); 1830 int length = readUnsignedShort(u + 5); 1831 readLabel(start, context.labels); 1832 readLabel(start + length, context.labels); 1833 u += 6; 1834 } 1835 u += 3; 1836 break; 1837 case 0x47: // CAST 1838 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT 1839 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT 1840 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT 1841 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT 1842 u += 4; 1843 break; 1844 // case 0x10: // CLASS_EXTENDS 1845 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND 1846 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND 1847 // case 0x17: // THROWS 1848 // case 0x42: // EXCEPTION_PARAMETER 1849 // case 0x43: // INSTANCEOF 1850 // case 0x44: // NEW 1851 // case 0x45: // CONSTRUCTOR_REFERENCE 1852 // case 0x46: // METHOD_REFERENCE 1853 default: 1854 u += 3; 1855 break; 1856 } 1857 int pathLength = readByte(u); 1858 if ((target >>> 24) == 0x42) { 1859 TypePath path = pathLength == 0 ? null : new TypePath(b, u); 1860 u += 1 + 2 * pathLength; 1861 u = readAnnotationValues(u + 2, c, true, 1862 mv.visitTryCatchAnnotation(target, path, 1863 readUTF8(u, c), visible)); 1864 } else { 1865 u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null); 1866 } 1867 } 1868 return offsets; 1869 } 1870 1871 /** 1872 * Parses the header of a type annotation to extract its target_type and 1873 * target_path (the result is stored in the given context), and returns the 1874 * start offset of the rest of the type_annotation structure (i.e. the 1875 * offset to the type_index field, which is followed by 1876 * num_element_value_pairs and then the name,value pairs). 1877 * 1878 * @param context 1879 * information about the class being parsed. This is where the 1880 * extracted target_type and target_path must be stored. 1881 * @param u 1882 * the start offset of a type_annotation structure. 1883 * @return the start offset of the rest of the type_annotation structure. 1884 */ 1885 private int readAnnotationTarget(final Context context, int u) { 1886 int target = readInt(u); 1887 switch (target >>> 24) { 1888 case 0x00: // CLASS_TYPE_PARAMETER 1889 case 0x01: // METHOD_TYPE_PARAMETER 1890 case 0x16: // METHOD_FORMAL_PARAMETER 1891 target &= 0xFFFF0000; 1892 u += 2; 1893 break; 1894 case 0x13: // FIELD 1895 case 0x14: // METHOD_RETURN 1896 case 0x15: // METHOD_RECEIVER 1897 target &= 0xFF000000; 1898 u += 1; 1899 break; 1900 case 0x40: // LOCAL_VARIABLE 1901 case 0x41: { // RESOURCE_VARIABLE 1902 target &= 0xFF000000; 1903 int n = readUnsignedShort(u + 1); 1904 context.start = new Label[n]; 1905 context.end = new Label[n]; 1906 context.index = new int[n]; 1907 u += 3; 1908 for (int i = 0; i < n; ++i) { 1909 int start = readUnsignedShort(u); 1910 int length = readUnsignedShort(u + 2); 1911 context.start[i] = readLabel(start, context.labels); 1912 context.end[i] = readLabel(start + length, context.labels); 1913 context.index[i] = readUnsignedShort(u + 4); 1914 u += 6; 1915 } 1916 break; 1917 } 1918 case 0x47: // CAST 1919 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT 1920 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT 1921 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT 1922 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT 1923 target &= 0xFF0000FF; 1924 u += 4; 1925 break; 1926 // case 0x10: // CLASS_EXTENDS 1927 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND 1928 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND 1929 // case 0x17: // THROWS 1930 // case 0x42: // EXCEPTION_PARAMETER 1931 // case 0x43: // INSTANCEOF 1932 // case 0x44: // NEW 1933 // case 0x45: // CONSTRUCTOR_REFERENCE 1934 // case 0x46: // METHOD_REFERENCE 1935 default: 1936 target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000; 1937 u += 3; 1938 break; 1939 } 1940 int pathLength = readByte(u); 1941 context.typeRef = target; 1942 context.typePath = pathLength == 0 ? null : new TypePath(b, u); 1943 return u + 1 + 2 * pathLength; 1944 } 1945 1946 /** 1947 * Reads parameter annotations and makes the given visitor visit them. 1948 * 1949 * @param mv 1950 * the visitor that must visit the annotations. 1951 * @param context 1952 * information about the class being parsed. 1953 * @param v 1954 * start offset in {@link #b b} of the annotations to be read. 1955 * @param visible 1956 * <tt>true</tt> if the annotations to be read are visible at 1957 * runtime. 1958 */ 1959 private void readParameterAnnotations(final MethodVisitor mv, 1960 final Context context, int v, final boolean visible) { 1961 int i; 1962 int n = b[v++] & 0xFF; 1963 // workaround for a bug in javac (javac compiler generates a parameter 1964 // annotation array whose size is equal to the number of parameters in 1965 // the Java source file, while it should generate an array whose size is 1966 // equal to the number of parameters in the method descriptor - which 1967 // includes the synthetic parameters added by the compiler). This work- 1968 // around supposes that the synthetic parameters are the first ones. 1969 int synthetics = Type.getArgumentTypes(context.desc).length - n; 1970 AnnotationVisitor av; 1971 for (i = 0; i < synthetics; ++i) { 1972 // virtual annotation to detect synthetic parameters in MethodWriter 1973 av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false); 1974 if (av != null) { 1975 av.visitEnd(); 1976 } 1977 } 1978 char[] c = context.buffer; 1979 for (; i < n + synthetics; ++i) { 1980 int j = readUnsignedShort(v); 1981 v += 2; 1982 for (; j > 0; --j) { 1983 av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible); 1984 v = readAnnotationValues(v + 2, c, true, av); 1985 } 1986 } 1987 } 1988 1989 /** 1990 * Reads the values of an annotation and makes the given visitor visit them. 1991 * 1992 * @param v 1993 * the start offset in {@link #b b} of the values to be read 1994 * (including the unsigned short that gives the number of 1995 * values). 1996 * @param buf 1997 * buffer to be used to call {@link #readUTF8 readUTF8}, 1998 * {@link #readClass(int,char[]) readClass} or {@link #readConst 1999 * readConst}. 2000 * @param named 2001 * if the annotation values are named or not. 2002 * @param av 2003 * the visitor that must visit the values. 2004 * @return the end offset of the annotation values. 2005 */ 2006 private int readAnnotationValues(int v, final char[] buf, 2007 final boolean named, final AnnotationVisitor av) { 2008 int i = readUnsignedShort(v); 2009 v += 2; 2010 if (named) { 2011 for (; i > 0; --i) { 2012 v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av); 2013 } 2014 } else { 2015 for (; i > 0; --i) { 2016 v = readAnnotationValue(v, buf, null, av); 2017 } 2018 } 2019 if (av != null) { 2020 av.visitEnd(); 2021 } 2022 return v; 2023 } 2024 2025 /** 2026 * Reads a value of an annotation and makes the given visitor visit it. 2027 * 2028 * @param v 2029 * the start offset in {@link #b b} of the value to be read 2030 * (<i>not including the value name constant pool index</i>). 2031 * @param buf 2032 * buffer to be used to call {@link #readUTF8 readUTF8}, 2033 * {@link #readClass(int,char[]) readClass} or {@link #readConst 2034 * readConst}. 2035 * @param name 2036 * the name of the value to be read. 2037 * @param av 2038 * the visitor that must visit the value. 2039 * @return the end offset of the annotation value. 2040 */ 2041 private int readAnnotationValue(int v, final char[] buf, final String name, 2042 final AnnotationVisitor av) { 2043 int i; 2044 if (av == null) { 2045 switch (b[v] & 0xFF) { 2046 case 'e': // enum_const_value 2047 return v + 5; 2048 case '@': // annotation_value 2049 return readAnnotationValues(v + 3, buf, true, null); 2050 case '[': // array_value 2051 return readAnnotationValues(v + 1, buf, false, null); 2052 default: 2053 return v + 3; 2054 } 2055 } 2056 switch (b[v++] & 0xFF) { 2057 case 'I': // pointer to CONSTANT_Integer 2058 case 'J': // pointer to CONSTANT_Long 2059 case 'F': // pointer to CONSTANT_Float 2060 case 'D': // pointer to CONSTANT_Double 2061 av.visit(name, readConst(readUnsignedShort(v), buf)); 2062 v += 2; 2063 break; 2064 case 'B': // pointer to CONSTANT_Byte 2065 av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); 2066 v += 2; 2067 break; 2068 case 'Z': // pointer to CONSTANT_Boolean 2069 av.visit(name, 2070 readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE 2071 : Boolean.TRUE); 2072 v += 2; 2073 break; 2074 case 'S': // pointer to CONSTANT_Short 2075 av.visit(name, (short) readInt(items[readUnsignedShort(v)])); 2076 v += 2; 2077 break; 2078 case 'C': // pointer to CONSTANT_Char 2079 av.visit(name, (char) readInt(items[readUnsignedShort(v)])); 2080 v += 2; 2081 break; 2082 case 's': // pointer to CONSTANT_Utf8 2083 av.visit(name, readUTF8(v, buf)); 2084 v += 2; 2085 break; 2086 case 'e': // enum_const_value 2087 av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); 2088 v += 4; 2089 break; 2090 case 'c': // class_info 2091 av.visit(name, Type.getType(readUTF8(v, buf))); 2092 v += 2; 2093 break; 2094 case '@': // annotation_value 2095 v = readAnnotationValues(v + 2, buf, true, 2096 av.visitAnnotation(name, readUTF8(v, buf))); 2097 break; 2098 case '[': // array_value 2099 int size = readUnsignedShort(v); 2100 v += 2; 2101 if (size == 0) { 2102 return readAnnotationValues(v - 2, buf, false, 2103 av.visitArray(name)); 2104 } 2105 switch (this.b[v++] & 0xFF) { 2106 case 'B': 2107 byte[] bv = new byte[size]; 2108 for (i = 0; i < size; i++) { 2109 bv[i] = (byte) readInt(items[readUnsignedShort(v)]); 2110 v += 3; 2111 } 2112 av.visit(name, bv); 2113 --v; 2114 break; 2115 case 'Z': 2116 boolean[] zv = new boolean[size]; 2117 for (i = 0; i < size; i++) { 2118 zv[i] = readInt(items[readUnsignedShort(v)]) != 0; 2119 v += 3; 2120 } 2121 av.visit(name, zv); 2122 --v; 2123 break; 2124 case 'S': 2125 short[] sv = new short[size]; 2126 for (i = 0; i < size; i++) { 2127 sv[i] = (short) readInt(items[readUnsignedShort(v)]); 2128 v += 3; 2129 } 2130 av.visit(name, sv); 2131 --v; 2132 break; 2133 case 'C': 2134 char[] cv = new char[size]; 2135 for (i = 0; i < size; i++) { 2136 cv[i] = (char) readInt(items[readUnsignedShort(v)]); 2137 v += 3; 2138 } 2139 av.visit(name, cv); 2140 --v; 2141 break; 2142 case 'I': 2143 int[] iv = new int[size]; 2144 for (i = 0; i < size; i++) { 2145 iv[i] = readInt(items[readUnsignedShort(v)]); 2146 v += 3; 2147 } 2148 av.visit(name, iv); 2149 --v; 2150 break; 2151 case 'J': 2152 long[] lv = new long[size]; 2153 for (i = 0; i < size; i++) { 2154 lv[i] = readLong(items[readUnsignedShort(v)]); 2155 v += 3; 2156 } 2157 av.visit(name, lv); 2158 --v; 2159 break; 2160 case 'F': 2161 float[] fv = new float[size]; 2162 for (i = 0; i < size; i++) { 2163 fv[i] = Float 2164 .intBitsToFloat(readInt(items[readUnsignedShort(v)])); 2165 v += 3; 2166 } 2167 av.visit(name, fv); 2168 --v; 2169 break; 2170 case 'D': 2171 double[] dv = new double[size]; 2172 for (i = 0; i < size; i++) { 2173 dv[i] = Double 2174 .longBitsToDouble(readLong(items[readUnsignedShort(v)])); 2175 v += 3; 2176 } 2177 av.visit(name, dv); 2178 --v; 2179 break; 2180 default: 2181 v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); 2182 } 2183 } 2184 return v; 2185 } 2186 2187 /** 2188 * Computes the implicit frame of the method currently being parsed (as 2189 * defined in the given {@link Context}) and stores it in the given context. 2190 * 2191 * @param frame 2192 * information about the class being parsed. 2193 */ 2194 private void getImplicitFrame(final Context frame) { 2195 String desc = frame.desc; 2196 Object[] locals = frame.local; 2197 int local = 0; 2198 if ((frame.access & Opcodes.ACC_STATIC) == 0) { 2199 if ("<init>".equals(frame.name)) { 2200 locals[local++] = Opcodes.UNINITIALIZED_THIS; 2201 } else { 2202 locals[local++] = readClass(header + 2, frame.buffer); 2203 } 2204 } 2205 int i = 1; 2206 loop: while (true) { 2207 int j = i; 2208 switch (desc.charAt(i++)) { 2209 case 'Z': 2210 case 'C': 2211 case 'B': 2212 case 'S': 2213 case 'I': 2214 locals[local++] = Opcodes.INTEGER; 2215 break; 2216 case 'F': 2217 locals[local++] = Opcodes.FLOAT; 2218 break; 2219 case 'J': 2220 locals[local++] = Opcodes.LONG; 2221 break; 2222 case 'D': 2223 locals[local++] = Opcodes.DOUBLE; 2224 break; 2225 case '[': 2226 while (desc.charAt(i) == '[') { 2227 ++i; 2228 } 2229 if (desc.charAt(i) == 'L') { 2230 ++i; 2231 while (desc.charAt(i) != ';') { 2232 ++i; 2233 } 2234 } 2235 locals[local++] = desc.substring(j, ++i); 2236 break; 2237 case 'L': 2238 while (desc.charAt(i) != ';') { 2239 ++i; 2240 } 2241 locals[local++] = desc.substring(j + 1, i++); 2242 break; 2243 default: 2244 break loop; 2245 } 2246 } 2247 frame.localCount = local; 2248 } 2249 2250 /** 2251 * Reads a stack map frame and stores the result in the given 2252 * {@link Context} object. 2253 * 2254 * @param stackMap 2255 * the start offset of a stack map frame in the class file. 2256 * @param zip 2257 * if the stack map frame at stackMap is compressed or not. 2258 * @param unzip 2259 * if the stack map frame must be uncompressed. 2260 * @param frame 2261 * where the parsed stack map frame must be stored. 2262 * @return the offset of the first byte following the parsed frame. 2263 */ 2264 private int readFrame(int stackMap, boolean zip, boolean unzip, 2265 Context frame) { 2266 char[] c = frame.buffer; 2267 Label[] labels = frame.labels; 2268 int tag; 2269 int delta; 2270 if (zip) { 2271 tag = b[stackMap++] & 0xFF; 2272 } else { 2273 tag = MethodWriter.FULL_FRAME; 2274 frame.offset = -1; 2275 } 2276 frame.localDiff = 0; 2277 if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) { 2278 delta = tag; 2279 frame.mode = Opcodes.F_SAME; 2280 frame.stackCount = 0; 2281 } else if (tag < MethodWriter.RESERVED) { 2282 delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; 2283 stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); 2284 frame.mode = Opcodes.F_SAME1; 2285 frame.stackCount = 1; 2286 } else { 2287 delta = readUnsignedShort(stackMap); 2288 stackMap += 2; 2289 if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { 2290 stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); 2291 frame.mode = Opcodes.F_SAME1; 2292 frame.stackCount = 1; 2293 } else if (tag >= MethodWriter.CHOP_FRAME 2294 && tag < MethodWriter.SAME_FRAME_EXTENDED) { 2295 frame.mode = Opcodes.F_CHOP; 2296 frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag; 2297 frame.localCount -= frame.localDiff; 2298 frame.stackCount = 0; 2299 } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) { 2300 frame.mode = Opcodes.F_SAME; 2301 frame.stackCount = 0; 2302 } else if (tag < MethodWriter.FULL_FRAME) { 2303 int local = unzip ? frame.localCount : 0; 2304 for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) { 2305 stackMap = readFrameType(frame.local, local++, stackMap, c, 2306 labels); 2307 } 2308 frame.mode = Opcodes.F_APPEND; 2309 frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED; 2310 frame.localCount += frame.localDiff; 2311 frame.stackCount = 0; 2312 } else { // if (tag == FULL_FRAME) { 2313 frame.mode = Opcodes.F_FULL; 2314 int n = readUnsignedShort(stackMap); 2315 stackMap += 2; 2316 frame.localDiff = n; 2317 frame.localCount = n; 2318 for (int local = 0; n > 0; n--) { 2319 stackMap = readFrameType(frame.local, local++, stackMap, c, 2320 labels); 2321 } 2322 n = readUnsignedShort(stackMap); 2323 stackMap += 2; 2324 frame.stackCount = n; 2325 for (int stack = 0; n > 0; n--) { 2326 stackMap = readFrameType(frame.stack, stack++, stackMap, c, 2327 labels); 2328 } 2329 } 2330 } 2331 frame.offset += delta + 1; 2332 readLabel(frame.offset, labels); 2333 return stackMap; 2334 } 2335 2336 /** 2337 * Reads a stack map frame type and stores it at the given index in the 2338 * given array. 2339 * 2340 * @param frame 2341 * the array where the parsed type must be stored. 2342 * @param index 2343 * the index in 'frame' where the parsed type must be stored. 2344 * @param v 2345 * the start offset of the stack map frame type to read. 2346 * @param buf 2347 * a buffer to read strings. 2348 * @param labels 2349 * the labels of the method currently being parsed, indexed by 2350 * their offset. If the parsed type is an Uninitialized type, a 2351 * new label for the corresponding NEW instruction is stored in 2352 * this array if it does not already exist. 2353 * @return the offset of the first byte after the parsed type. 2354 */ 2355 private int readFrameType(final Object[] frame, final int index, int v, 2356 final char[] buf, final Label[] labels) { 2357 int type = b[v++] & 0xFF; 2358 switch (type) { 2359 case 0: 2360 frame[index] = Opcodes.TOP; 2361 break; 2362 case 1: 2363 frame[index] = Opcodes.INTEGER; 2364 break; 2365 case 2: 2366 frame[index] = Opcodes.FLOAT; 2367 break; 2368 case 3: 2369 frame[index] = Opcodes.DOUBLE; 2370 break; 2371 case 4: 2372 frame[index] = Opcodes.LONG; 2373 break; 2374 case 5: 2375 frame[index] = Opcodes.NULL; 2376 break; 2377 case 6: 2378 frame[index] = Opcodes.UNINITIALIZED_THIS; 2379 break; 2380 case 7: // Object 2381 frame[index] = readClass(v, buf); 2382 v += 2; 2383 break; 2384 default: // Uninitialized 2385 frame[index] = readLabel(readUnsignedShort(v), labels); 2386 v += 2; 2387 } 2388 return v; 2389 } 2390 2391 /** 2392 * Returns the label corresponding to the given offset. The default 2393 * implementation of this method creates a label for the given offset if it 2394 * has not been already created. 2395 * 2396 * @param offset 2397 * a bytecode offset in a method. 2398 * @param labels 2399 * the already created labels, indexed by their offset. If a 2400 * label already exists for offset this method must not create a 2401 * new one. Otherwise it must store the new label in this array. 2402 * @return a non null Label, which must be equal to labels[offset]. 2403 */ 2404 protected Label readLabel(int offset, Label[] labels) { 2405 // SPRING PATCH: leniently handle offset mismatch 2406 if (offset >= labels.length) { 2407 return new Label(); 2408 } 2409 // END OF PATCH 2410 if (labels[offset] == null) { 2411 labels[offset] = new Label(); 2412 } 2413 return labels[offset]; 2414 } 2415 2416 /** 2417 * Returns the start index of the attribute_info structure of this class. 2418 * 2419 * @return the start index of the attribute_info structure of this class. 2420 */ 2421 private int getAttributes() { 2422 // skips the header 2423 int u = header + 8 + readUnsignedShort(header + 6) * 2; 2424 // skips fields and methods 2425 for (int i = readUnsignedShort(u); i > 0; --i) { 2426 for (int j = readUnsignedShort(u + 8); j > 0; --j) { 2427 u += 6 + readInt(u + 12); 2428 } 2429 u += 8; 2430 } 2431 u += 2; 2432 for (int i = readUnsignedShort(u); i > 0; --i) { 2433 for (int j = readUnsignedShort(u + 8); j > 0; --j) { 2434 u += 6 + readInt(u + 12); 2435 } 2436 u += 8; 2437 } 2438 // the attribute_info structure starts just after the methods 2439 return u + 2; 2440 } 2441 2442 /** 2443 * Reads an attribute in {@link #b b}. 2444 * 2445 * @param attrs 2446 * prototypes of the attributes that must be parsed during the 2447 * visit of the class. Any attribute whose type is not equal to 2448 * the type of one the prototypes is ignored (i.e. an empty 2449 * {@link Attribute} instance is returned). 2450 * @param type 2451 * the type of the attribute. 2452 * @param off 2453 * index of the first byte of the attribute's content in 2454 * {@link #b b}. The 6 attribute header bytes, containing the 2455 * type and the length of the attribute, are not taken into 2456 * account here (they have already been read). 2457 * @param len 2458 * the length of the attribute's content. 2459 * @param buf 2460 * buffer to be used to call {@link #readUTF8 readUTF8}, 2461 * {@link #readClass(int,char[]) readClass} or {@link #readConst 2462 * readConst}. 2463 * @param codeOff 2464 * index of the first byte of code's attribute content in 2465 * {@link #b b}, or -1 if the attribute to be read is not a code 2466 * attribute. The 6 attribute header bytes, containing the type 2467 * and the length of the attribute, are not taken into account 2468 * here. 2469 * @param labels 2470 * the labels of the method's code, or <tt>null</tt> if the 2471 * attribute to be read is not a code attribute. 2472 * @return the attribute that has been read, or <tt>null</tt> to skip this 2473 * attribute. 2474 */ 2475 private Attribute readAttribute(final Attribute[] attrs, final String type, 2476 final int off, final int len, final char[] buf, final int codeOff, 2477 final Label[] labels) { 2478 for (int i = 0; i < attrs.length; ++i) { 2479 if (attrs[i].type.equals(type)) { 2480 return attrs[i].read(this, off, len, buf, codeOff, labels); 2481 } 2482 } 2483 return new Attribute(type).read(this, off, len, null, -1, null); 2484 } 2485 2486 // ------------------------------------------------------------------------ 2487 // Utility methods: low level parsing 2488 // ------------------------------------------------------------------------ 2489 2490 /** 2491 * Returns the number of constant pool items in {@link #b b}. 2492 * 2493 * @return the number of constant pool items in {@link #b b}. 2494 */ 2495 public int getItemCount() { 2496 return items.length; 2497 } 2498 2499 /** 2500 * Returns the start index of the constant pool item in {@link #b b}, plus 2501 * one. <i>This method is intended for {@link Attribute} sub classes, and is 2502 * normally not needed by class generators or adapters.</i> 2503 * 2504 * @param item 2505 * the index a constant pool item. 2506 * @return the start index of the constant pool item in {@link #b b}, plus 2507 * one. 2508 */ 2509 public int getItem(final int item) { 2510 return items[item]; 2511 } 2512 2513 /** 2514 * Returns the maximum length of the strings contained in the constant pool 2515 * of the class. 2516 * 2517 * @return the maximum length of the strings contained in the constant pool 2518 * of the class. 2519 */ 2520 public int getMaxStringLength() { 2521 return maxStringLength; 2522 } 2523 2524 /** 2525 * Reads a byte value in {@link #b b}. <i>This method is intended for 2526 * {@link Attribute} sub classes, and is normally not needed by class 2527 * generators or adapters.</i> 2528 * 2529 * @param index 2530 * the start index of the value to be read in {@link #b b}. 2531 * @return the read value. 2532 */ 2533 public int readByte(final int index) { 2534 return b[index] & 0xFF; 2535 } 2536 2537 /** 2538 * Reads an unsigned short value in {@link #b b}. <i>This method is intended 2539 * for {@link Attribute} sub classes, and is normally not needed by class 2540 * generators or adapters.</i> 2541 * 2542 * @param index 2543 * the start index of the value to be read in {@link #b b}. 2544 * @return the read value. 2545 */ 2546 public int readUnsignedShort(final int index) { 2547 byte[] b = this.b; 2548 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 2549 } 2550 2551 /** 2552 * Reads a signed short value in {@link #b b}. <i>This method is intended 2553 * for {@link Attribute} sub classes, and is normally not needed by class 2554 * generators or adapters.</i> 2555 * 2556 * @param index 2557 * the start index of the value to be read in {@link #b b}. 2558 * @return the read value. 2559 */ 2560 public short readShort(final int index) { 2561 byte[] b = this.b; 2562 return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 2563 } 2564 2565 /** 2566 * Reads a signed int value in {@link #b b}. <i>This method is intended for 2567 * {@link Attribute} sub classes, and is normally not needed by class 2568 * generators or adapters.</i> 2569 * 2570 * @param index 2571 * the start index of the value to be read in {@link #b b}. 2572 * @return the read value. 2573 */ 2574 public int readInt(final int index) { 2575 byte[] b = this.b; 2576 return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) 2577 | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); 2578 } 2579 2580 /** 2581 * Reads a signed long value in {@link #b b}. <i>This method is intended for 2582 * {@link Attribute} sub classes, and is normally not needed by class 2583 * generators or adapters.</i> 2584 * 2585 * @param index 2586 * the start index of the value to be read in {@link #b b}. 2587 * @return the read value. 2588 */ 2589 public long readLong(final int index) { 2590 long l1 = readInt(index); 2591 long l0 = readInt(index + 4) & 0xFFFFFFFFL; 2592 return (l1 << 32) | l0; 2593 } 2594 2595 /** 2596 * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method 2597 * is intended for {@link Attribute} sub classes, and is normally not needed 2598 * by class generators or adapters.</i> 2599 * 2600 * @param index 2601 * the start index of an unsigned short value in {@link #b b}, 2602 * whose value is the index of an UTF8 constant pool item. 2603 * @param buf 2604 * buffer to be used to read the item. This buffer must be 2605 * sufficiently large. It is not automatically resized. 2606 * @return the String corresponding to the specified UTF8 item. 2607 */ 2608 public String readUTF8(int index, final char[] buf) { 2609 int item = readUnsignedShort(index); 2610 if (index == 0 || item == 0) { 2611 return null; 2612 } 2613 String s = strings[item]; 2614 if (s != null) { 2615 return s; 2616 } 2617 index = items[item]; 2618 return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf); 2619 } 2620 2621 /** 2622 * Reads UTF8 string in {@link #b b}. 2623 * 2624 * @param index 2625 * start offset of the UTF8 string to be read. 2626 * @param utfLen 2627 * length of the UTF8 string to be read. 2628 * @param buf 2629 * buffer to be used to read the string. This buffer must be 2630 * sufficiently large. It is not automatically resized. 2631 * @return the String corresponding to the specified UTF8 string. 2632 */ 2633 private String readUTF(int index, final int utfLen, final char[] buf) { 2634 int endIndex = index + utfLen; 2635 byte[] b = this.b; 2636 int strLen = 0; 2637 int c; 2638 int st = 0; 2639 char cc = 0; 2640 while (index < endIndex) { 2641 c = b[index++]; 2642 switch (st) { 2643 case 0: 2644 c = c & 0xFF; 2645 if (c < 0x80) { // 0xxxxxxx 2646 buf[strLen++] = (char) c; 2647 } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx 2648 cc = (char) (c & 0x1F); 2649 st = 1; 2650 } else { // 1110 xxxx 10xx xxxx 10xx xxxx 2651 cc = (char) (c & 0x0F); 2652 st = 2; 2653 } 2654 break; 2655 2656 case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char 2657 buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); 2658 st = 0; 2659 break; 2660 2661 case 2: // byte 2 of 3-byte char 2662 cc = (char) ((cc << 6) | (c & 0x3F)); 2663 st = 1; 2664 break; 2665 } 2666 } 2667 return new String(buf, 0, strLen); 2668 } 2669 2670 /** 2671 * Read a stringish constant item (CONSTANT_Class, CONSTANT_String, 2672 * CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package 2673 * @param index 2674 * @param buf 2675 * @return 2676 */ 2677 private String readStringish(final int index, final char[] buf) { 2678 // computes the start index of the item in b 2679 // and reads the CONSTANT_Utf8 item designated by 2680 // the first two bytes of this item 2681 return readUTF8(items[readUnsignedShort(index)], buf); 2682 } 2683 2684 /** 2685 * Reads a class constant pool item in {@link #b b}. <i>This method is 2686 * intended for {@link Attribute} sub classes, and is normally not needed by 2687 * class generators or adapters.</i> 2688 * 2689 * @param index 2690 * the start index of an unsigned short value in {@link #b b}, 2691 * whose value is the index of a class constant pool item. 2692 * @param buf 2693 * buffer to be used to read the item. This buffer must be 2694 * sufficiently large. It is not automatically resized. 2695 * @return the String corresponding to the specified class item. 2696 */ 2697 public String readClass(final int index, final char[] buf) { 2698 return readStringish(index, buf); 2699 } 2700 2701 /** 2702 * Reads a module constant pool item in {@link #b b}. <i>This method is 2703 * intended for {@link Attribute} sub classes, and is normally not needed by 2704 * class generators or adapters.</i> 2705 * 2706 * @param index 2707 * the start index of an unsigned short value in {@link #b b}, 2708 * whose value is the index of a module constant pool item. 2709 * @param buf 2710 * buffer to be used to read the item. This buffer must be 2711 * sufficiently large. It is not automatically resized. 2712 * @return the String corresponding to the specified module item. 2713 */ 2714 public String readModule(final int index, final char[] buf) { 2715 return readStringish(index, buf); 2716 } 2717 2718 /** 2719 * Reads a module constant pool item in {@link #b b}. <i>This method is 2720 * intended for {@link Attribute} sub classes, and is normally not needed by 2721 * class generators or adapters.</i> 2722 * 2723 * @param index 2724 * the start index of an unsigned short value in {@link #b b}, 2725 * whose value is the index of a module constant pool item. 2726 * @param buf 2727 * buffer to be used to read the item. This buffer must be 2728 * sufficiently large. It is not automatically resized. 2729 * @return the String corresponding to the specified module item. 2730 */ 2731 public String readPackage(final int index, final char[] buf) { 2732 return readStringish(index, buf); 2733 } 2734 2735 /** 2736 * Reads a numeric or string constant pool item in {@link #b b}. <i>This 2737 * method is intended for {@link Attribute} sub classes, and is normally not 2738 * needed by class generators or adapters.</i> 2739 * 2740 * @param item 2741 * the index of a constant pool item. 2742 * @param buf 2743 * buffer to be used to read the item. This buffer must be 2744 * sufficiently large. It is not automatically resized. 2745 * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, 2746 * {@link String}, {@link Type} or {@link Handle} corresponding to 2747 * the given constant pool item. 2748 */ 2749 public Object readConst(final int item, final char[] buf) { 2750 int index = items[item]; 2751 switch (b[index - 1]) { 2752 case ClassWriter.INT: 2753 return readInt(index); 2754 case ClassWriter.FLOAT: 2755 return Float.intBitsToFloat(readInt(index)); 2756 case ClassWriter.LONG: 2757 return readLong(index); 2758 case ClassWriter.DOUBLE: 2759 return Double.longBitsToDouble(readLong(index)); 2760 case ClassWriter.CLASS: 2761 return Type.getObjectType(readUTF8(index, buf)); 2762 case ClassWriter.STR: 2763 return readUTF8(index, buf); 2764 case ClassWriter.MTYPE: 2765 return Type.getMethodType(readUTF8(index, buf)); 2766 default: // case ClassWriter.HANDLE_BASE + [1..9]: 2767 int tag = readByte(index); 2768 int[] items = this.items; 2769 int cpIndex = items[readUnsignedShort(index + 1)]; 2770 boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; 2771 String owner = readClass(cpIndex, buf); 2772 cpIndex = items[readUnsignedShort(cpIndex + 2)]; 2773 String name = readUTF8(cpIndex, buf); 2774 String desc = readUTF8(cpIndex + 2, buf); 2775 return new Handle(tag, owner, name, desc, itf); 2776 } 2777 } 2778}