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