1 30 31 package oracle.toplink.libraries.asm; 32 33 import java.io.InputStream ; 34 import java.io.IOException ; 35 36 44 45 public class ClassReader { 46 47 52 53 public final byte[] b; 54 55 59 60 private int[] items; 61 62 70 71 private String [] strings; 72 73 76 77 private int maxStringLength; 78 79 83 84 private int header; 85 86 90 95 96 public ClassReader (final byte[] b) { 97 this(b, 0, b.length); 98 } 99 100 107 108 public ClassReader (final byte[] b, final int off, final int len) { 109 this.b = b; 110 items = new int[readUnsignedShort(off + 8)]; 112 strings = new String [items.length]; 113 int max = 0; 114 int index = off + 10; 115 for (int i = 1; i < items.length; ++i) { 116 items[i] = index + 1; 117 int tag = b[index]; 118 int size; 119 switch (tag) { 120 case ClassWriter.FIELD: 121 case ClassWriter.METH: 122 case ClassWriter.IMETH: 123 case ClassWriter.INT: 124 case ClassWriter.FLOAT: 125 case ClassWriter.NAME_TYPE: 126 size = 5; 127 break; 128 case ClassWriter.LONG: 129 case ClassWriter.DOUBLE: 130 size = 9; 131 ++i; 132 break; 133 case ClassWriter.UTF8: 134 size = 3 + readUnsignedShort(index + 1); 135 max = (size > max ? size : max); 136 break; 137 default: 140 size = 3; 141 break; 142 } 143 index += size; 144 } 145 maxStringLength = max; 146 header = index; 148 } 149 150 156 157 public ClassReader (final InputStream is) throws IOException { 158 this(readClass(is)); 159 } 160 161 167 168 public ClassReader (final String name) throws IOException { 169 this(ClassLoader.getSystemResourceAsStream(name.replace('.','/') + ".class")); 170 } 171 172 179 180 private static byte[] readClass (final InputStream is) throws IOException { 181 if (is == null) { 182 throw new IOException ("Class not found"); 183 } 184 byte[] b = new byte[is.available()]; 185 int len = 0; 186 while (true) { 187 int n = is.read(b, len, b.length - len); 188 if (n == -1) { 189 if (len < b.length) { 190 byte[] c = new byte[len]; 191 System.arraycopy(b, 0, c, 0, len); 192 b = c; 193 } 194 return b; 195 } else { 196 len += n; 197 if (len == b.length) { 198 byte[] c = new byte[b.length + 1000]; 199 System.arraycopy(b, 0, c, 0, len); 200 b = c; 201 } 202 } 203 } 204 } 205 206 210 221 222 public void accept ( 223 final ClassVisitor classVisitor, 224 final boolean skipDebug) 225 { 226 accept(classVisitor, new Attribute[0], skipDebug); 227 } 228 229 243 244 public void accept ( 245 final ClassVisitor classVisitor, 246 final Attribute[] attrs, 247 final boolean skipDebug) 248 { 249 byte[] b = this.b; char[] c = new char[maxStringLength]; int i, j, k; int u, v, w; Attribute attr; 254 255 u = header; 257 int version = readInt(4); 258 int access = readUnsignedShort(u); 259 String className = readClass(u + 2, c); 260 v = items[readUnsignedShort(u + 4)]; 261 String superClassName = v == 0 ? null : readUTF8(v, c); 262 String [] implementedItfs = new String [readUnsignedShort(u + 6)]; 263 String sourceFile = null; 264 Attribute clattrs = null; 265 w = 0; 266 u += 8; 267 for (i = 0; i < implementedItfs.length; ++i) { 268 implementedItfs[i] = readClass(u, c); u += 2; 269 } 270 v = u; 272 i = readUnsignedShort(v); v += 2; 273 for ( ; i > 0; --i) { 274 j = readUnsignedShort(v + 6); 275 v += 8; 276 for ( ; j > 0; --j) { 277 v += 6 + readInt(v + 2); 278 } 279 } 280 i = readUnsignedShort(v); v += 2; 281 for ( ; i > 0; --i) { 282 j = readUnsignedShort(v + 6); 283 v += 8; 284 for ( ; j > 0; --j) { 285 v += 6 + readInt(v + 2); 286 } 287 } 288 i = readUnsignedShort(v); v += 2; 290 for ( ; i > 0; --i) { 291 String attrName = readUTF8(v, c); 292 if (attrName.equals("SourceFile")) { 293 sourceFile = readUTF8(v + 6, c); 294 } else if (attrName.equals("Deprecated")) { 295 access |= Constants.ACC_DEPRECATED; 296 } else if (attrName.equals("Synthetic")) { 297 access |= Constants.ACC_SYNTHETIC; 298 } else if (attrName.equals("InnerClasses")) { 299 w = v + 6; 300 } else { 301 attr = readAttribute( 302 attrs, attrName, v + 6, readInt(v + 2), c, -1, null); 303 if (attr != null) { 304 attr.next = clattrs; 305 clattrs = attr; 306 } 307 } 308 v += 6 + readInt(v + 2); 309 } 310 classVisitor.visit( 312 version, access, className, superClassName, implementedItfs, sourceFile); 313 314 if (w != 0) { 316 i = readUnsignedShort(w); w += 2; 317 for ( ; i > 0; --i) { 318 classVisitor.visitInnerClass( 319 readUnsignedShort(w) == 0 ? null : readClass(w, c), 320 readUnsignedShort(w + 2) == 0 ? null : readClass(w + 2, c), 321 readUnsignedShort(w + 4) == 0 ? null : readUTF8(w + 4, c), 322 readUnsignedShort(w + 6)); 323 w += 8; 324 } 325 } 326 327 i = readUnsignedShort(u); u += 2; 329 for ( ; i > 0; --i) { 330 access = readUnsignedShort(u); 331 String fieldName = readUTF8(u + 2, c); 332 String fieldDesc = readUTF8(u + 4, c); 333 Attribute fattrs = null; 334 int fieldValueItem = 0; 336 j = readUnsignedShort(u + 6); 337 u += 8; 338 for ( ; j > 0; --j) { 339 String attrName = readUTF8(u, c); 340 if (attrName.equals("ConstantValue")) { 341 fieldValueItem = readUnsignedShort(u + 6); 342 } else if (attrName.equals("Synthetic")) { 343 access |= Constants.ACC_SYNTHETIC; 344 } else if (attrName.equals("Deprecated")) { 345 access |= Constants.ACC_DEPRECATED; 346 } else { 347 attr = readAttribute( 348 attrs, attrName, u + 6, readInt(u + 2), c, -1, null); 349 if (attr != null) { 350 attr.next = fattrs; 351 fattrs = attr; 352 } 353 } 354 u += 6 + readInt(u + 2); 355 } 356 Object value = (fieldValueItem == 0 ? null : readConst(fieldValueItem, c)); 358 classVisitor.visitField(access, fieldName, fieldDesc, value, fattrs); 360 } 361 362 i = readUnsignedShort(u); u += 2; 364 for ( ; i > 0; --i) { 365 access = readUnsignedShort(u); 366 String methName = readUTF8(u + 2, c); 367 String methDesc = readUTF8(u + 4, c); 368 Attribute mattrs = null; 369 Attribute cattrs = null; 370 v = 0; 371 w = 0; 372 j = readUnsignedShort(u + 6); 374 u += 8; 375 for ( ; j > 0; --j) { 376 String attrName = readUTF8(u, c); u += 2; 377 int attrSize = readInt(u); u += 4; 378 if (attrName.equals("Code")) { 379 v = u; 380 } else if (attrName.equals("Exceptions")) { 381 w = u; 382 } else if (attrName.equals("Synthetic")) { 383 access |= Constants.ACC_SYNTHETIC; 384 } else if (attrName.equals("Deprecated")) { 385 access |= Constants.ACC_DEPRECATED; 386 } else { 387 attr = readAttribute(attrs, attrName, u, attrSize, c, -1, null); 388 if (attr != null) { 389 attr.next = mattrs; 390 mattrs = attr; 391 } 392 } 393 u += attrSize; 394 } 395 String [] exceptions; 397 if (w == 0) { 398 exceptions = null; 399 } else { 400 exceptions = new String [readUnsignedShort(w)]; w += 2; 401 for (j = 0; j < exceptions.length; ++j) { 402 exceptions[j] = readClass(w, c); w += 2; 403 } 404 } 405 406 CodeVisitor cv; 408 cv = classVisitor.visitMethod( 409 access, methName, methDesc, exceptions, mattrs); 410 if (cv != null && v != 0) { 411 int maxStack = readUnsignedShort(v); 412 int maxLocals = readUnsignedShort(v + 2); 413 int codeLength = readInt(v + 4); 414 v += 8; 415 416 int codeStart = v; 417 int codeEnd = v + codeLength; 418 419 int label; 421 Label[] labels = new Label[codeLength + 1]; 422 while (v < codeEnd) { 423 int opcode = b[v] & 0xFF; 424 switch (ClassWriter.TYPE[opcode]) { 425 case ClassWriter.NOARG_INSN: 426 case ClassWriter.IMPLVAR_INSN: 427 v += 1; 428 break; 429 case ClassWriter.LABEL_INSN: 430 label = v - codeStart + readShort(v + 1); 431 if (labels[label] == null) { 432 labels[label] = new Label(); 433 } 434 v += 3; 435 break; 436 case ClassWriter.LABELW_INSN: 437 label = v - codeStart + readInt(v + 1); 438 if (labels[label] == null) { 439 labels[label] = new Label(); 440 } 441 v += 5; 442 break; 443 case ClassWriter.WIDE_INSN: 444 opcode = b[v + 1] & 0xFF; 445 if (opcode == Constants.IINC) { 446 v += 6; 447 } else { 448 v += 4; 449 } 450 break; 451 case ClassWriter.TABL_INSN: 452 w = v - codeStart; 454 v = v + 4 - (w & 3); 455 label = w + readInt(v); v += 4; 457 if (labels[label] == null) { 458 labels[label] = new Label(); 459 } 460 j = readInt(v); v += 4; 461 j = readInt(v) - j + 1; v += 4; 462 for ( ; j > 0; --j) { 463 label = w + readInt(v); v += 4; 464 if (labels[label] == null) { 465 labels[label] = new Label(); 466 } 467 } 468 break; 469 case ClassWriter.LOOK_INSN: 470 w = v - codeStart; 472 v = v + 4 - (w & 3); 473 label = w + readInt(v); v += 4; 475 if (labels[label] == null) { 476 labels[label] = new Label(); 477 } 478 j = readInt(v); v += 4; 479 for ( ; j > 0; --j) { 480 v += 4; label = w + readInt(v); v += 4; 482 if (labels[label] == null) { 483 labels[label] = new Label(); 484 } 485 } 486 break; 487 case ClassWriter.VAR_INSN: 488 case ClassWriter.SBYTE_INSN: 489 case ClassWriter.LDC_INSN: 490 v += 2; 491 break; 492 case ClassWriter.SHORT_INSN: 493 case ClassWriter.LDCW_INSN: 494 case ClassWriter.FIELDORMETH_INSN: 495 case ClassWriter.TYPE_INSN: 496 case ClassWriter.IINC_INSN: 497 v += 3; 498 break; 499 case ClassWriter.ITFMETH_INSN: 500 v += 5; 501 break; 502 default: 504 v += 4; 505 break; 506 } 507 } 508 j = readUnsignedShort(v); v += 2; 510 for ( ; j > 0; --j) { 511 label = readUnsignedShort(v); 512 if (labels[label] == null) { 513 labels[label] = new Label(); 514 } 515 label = readUnsignedShort(v + 2); 516 if (labels[label] == null) { 517 labels[label] = new Label(); 518 } 519 label = readUnsignedShort(v + 4); 520 if (labels[label] == null) { 521 labels[label] = new Label(); 522 } 523 v += 8; 524 } 525 j = readUnsignedShort(v); v += 2; 527 for ( ; j > 0; --j) { 528 String attrName = readUTF8(v, c); 529 if (attrName.equals("LocalVariableTable")) { 530 if (!skipDebug) { 531 k = readUnsignedShort(v + 6); 532 w = v + 8; 533 for ( ; k > 0; --k) { 534 label = readUnsignedShort(w); 535 if (labels[label] == null) { 536 labels[label] = new Label(); 537 } 538 label += readUnsignedShort(w + 2); 539 if (labels[label] == null) { 540 labels[label] = new Label(); 541 } 542 w += 10; 543 } 544 } 545 } else if (attrName.equals("LineNumberTable")) { 546 if (!skipDebug) { 547 k = readUnsignedShort(v + 6); 548 w = v + 8; 549 for ( ; k > 0; --k) { 550 label = readUnsignedShort(w); 551 if (labels[label] == null) { 552 labels[label] = new Label(); 553 } 554 labels[label].line = readUnsignedShort(w + 2); 555 w += 4; 556 } 557 } 558 } else { 559 for (k = 0; k < attrs.length; ++k) { 560 if (attrs[k].type.equals(attrName)) { 561 attr = attrs[k].read( 562 this, v + 6, readInt(v + 2), c, codeStart - 8, labels); 563 if (attr != null) { 564 attr.next = cattrs; 565 cattrs = attr; 566 } 567 } 568 } 569 } 570 v += 6 + readInt(v + 2); 571 } 572 573 v = codeStart; 575 Label l; 576 while (v < codeEnd) { 577 w = v - codeStart; 578 l = labels[w]; 579 if (l != null) { 580 cv.visitLabel(l); 581 if (!skipDebug && l.line > 0) { 582 cv.visitLineNumber(l.line, l); 583 } 584 } 585 int opcode = b[v] & 0xFF; 586 switch (ClassWriter.TYPE[opcode]) { 587 case ClassWriter.NOARG_INSN: 588 cv.visitInsn(opcode); 589 v += 1; 590 break; 591 case ClassWriter.IMPLVAR_INSN: 592 if (opcode > Constants.ISTORE) { 593 opcode -= 59; cv.visitVarInsn(Constants.ISTORE + (opcode >> 2), opcode & 0x3); 595 } else { 596 opcode -= 26; cv.visitVarInsn(Constants.ILOAD + (opcode >> 2), opcode & 0x3); 598 } 599 v += 1; 600 break; 601 case ClassWriter.LABEL_INSN: 602 cv.visitJumpInsn(opcode, labels[w + readShort(v + 1)]); 603 v += 3; 604 break; 605 case ClassWriter.LABELW_INSN: 606 cv.visitJumpInsn(opcode - 33, labels[w + readInt(v + 1)]); 607 v += 5; 608 break; 609 case ClassWriter.WIDE_INSN: 610 opcode = b[v + 1] & 0xFF; 611 if (opcode == Constants.IINC) { 612 cv.visitIincInsn(readUnsignedShort(v + 2), readShort(v + 4)); 613 v += 6; 614 } else { 615 cv.visitVarInsn(opcode, readUnsignedShort(v + 2)); 616 v += 4; 617 } 618 break; 619 case ClassWriter.TABL_INSN: 620 v = v + 4 - (w & 3); 622 label = w + readInt(v); v += 4; 624 int min = readInt(v); v += 4; 625 int max = readInt(v); v += 4; 626 Label[] table = new Label[max - min + 1]; 627 for (j = 0; j < table.length; ++j) { 628 table[j] = labels[w + readInt(v)]; 629 v += 4; 630 } 631 cv.visitTableSwitchInsn(min, max, labels[label], table); 632 break; 633 case ClassWriter.LOOK_INSN: 634 v = v + 4 - (w & 3); 636 label = w + readInt(v); v += 4; 638 j = readInt(v); v += 4; 639 int[] keys = new int[j]; 640 Label[] values = new Label[j]; 641 for (j = 0; j < keys.length; ++j) { 642 keys[j] = readInt(v); v += 4; 643 values[j] = labels[w + readInt(v)]; v += 4; 644 } 645 cv.visitLookupSwitchInsn(labels[label], keys, values); 646 break; 647 case ClassWriter.VAR_INSN: 648 cv.visitVarInsn(opcode, b[v + 1] & 0xFF); 649 v += 2; 650 break; 651 case ClassWriter.SBYTE_INSN: 652 cv.visitIntInsn(opcode, b[v + 1]); 653 v += 2; 654 break; 655 case ClassWriter.SHORT_INSN: 656 cv.visitIntInsn(opcode, readShort(v + 1)); 657 v += 3; 658 break; 659 case ClassWriter.LDC_INSN: 660 cv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c)); 661 v += 2; 662 break; 663 case ClassWriter.LDCW_INSN: 664 cv.visitLdcInsn(readConst(readUnsignedShort(v + 1), c)); 665 v += 3; 666 break; 667 case ClassWriter.FIELDORMETH_INSN: 668 case ClassWriter.ITFMETH_INSN: 669 int cpIndex = items[readUnsignedShort(v + 1)]; 670 String iowner = readClass(cpIndex, c); 671 cpIndex = items[readUnsignedShort(cpIndex + 2)]; 672 String iname = readUTF8(cpIndex, c); 673 String idesc = readUTF8(cpIndex + 2, c); 674 if (opcode < Constants.INVOKEVIRTUAL) { 675 cv.visitFieldInsn(opcode, iowner, iname, idesc); 676 } else { 677 cv.visitMethodInsn(opcode, iowner, iname, idesc); 678 } 679 if (opcode == Constants.INVOKEINTERFACE) { 680 v += 5; 681 } else { 682 v += 3; 683 } 684 break; 685 case ClassWriter.TYPE_INSN: 686 cv.visitTypeInsn(opcode, readClass(v + 1, c)); 687 v += 3; 688 break; 689 case ClassWriter.IINC_INSN: 690 cv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]); 691 v += 3; 692 break; 693 default: 695 cv.visitMultiANewArrayInsn(readClass(v + 1, c), b[v + 3] & 0xFF); 696 v += 4; 697 break; 698 } 699 } 700 l = labels[codeEnd - codeStart]; 701 if (l != null) { 702 cv.visitLabel(l); 703 } 704 j = readUnsignedShort(v); v += 2; 706 for ( ; j > 0; --j) { 707 Label start = labels[readUnsignedShort(v)]; 708 Label end = labels[readUnsignedShort(v + 2)]; 709 Label handler = labels[readUnsignedShort(v + 4)]; 710 int type = readUnsignedShort(v + 6); 711 if (type == 0) { 712 cv.visitTryCatchBlock(start, end, handler, null); 713 } else { 714 cv.visitTryCatchBlock(start, end, handler, readUTF8(items[type], c)); 715 } 716 v += 8; 717 } 718 j = readUnsignedShort(v); v += 2; 720 if (!skipDebug) { 721 for ( ; j > 0; --j) { 722 String attrName = readUTF8(v, c); 723 if (attrName.equals("LocalVariableTable")) { 724 k = readUnsignedShort(v + 6); 725 w = v + 8; 726 for ( ; k > 0; --k) { 727 label = readUnsignedShort(w); 728 Label start = labels[label]; 729 label += readUnsignedShort(w + 2); 730 Label end = labels[label]; 731 cv.visitLocalVariable( 732 readUTF8(w + 4, c), 733 readUTF8(w + 6, c), 734 start, 735 end, 736 readUnsignedShort(w + 8)); 737 w += 10; 738 } 739 } 740 v += 6 + readInt(v + 2); 741 } 742 } 743 while (cattrs != null) { 745 attr = cattrs.next; 746 cattrs.next = null; 747 cv.visitAttribute(cattrs); 748 cattrs = attr; 749 } 750 cv.visitMaxs(maxStack, maxLocals); 752 } 753 } 754 Attribute last = null; 756 attr = clattrs; 757 while (attr != null) { 758 Attribute next = attr.next; 759 attr.next = last; 760 last = attr; 761 attr = next; 762 } 763 while (last != null) { 764 attr = last.next; 765 last.next = null; 766 classVisitor.visitAttribute(last); 767 last = attr; 768 } 769 classVisitor.visitEnd(); 771 } 772 773 777 786 787 public int getItem (final int item) { 788 return items[item]; 789 } 790 791 799 800 public int readByte (final int index) { 801 return b[index] & 0xFF; 802 } 803 804 812 813 public int readUnsignedShort (final int index) { 814 byte[] b = this.b; 815 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 816 } 817 818 826 827 public short readShort (final int index) { 828 byte[] b = this.b; 829 return (short)(((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 830 } 831 832 840 841 public int readInt (final int index) { 842 byte[] b = this.b; 843 return ((b[index] & 0xFF) << 24) | 844 ((b[index + 1] & 0xFF) << 16) | 845 ((b[index + 2] & 0xFF) << 8) | 846 (b[index + 3] & 0xFF); 847 } 848 849 857 858 public long readLong (final int index) { 859 long l1 = readInt(index); 860 long l0 = readInt(index + 4) & 0xFFFFFFFFL; 861 return (l1 << 32) | l0; 862 } 863 864 875 876 public String readUTF8 (int index, final char[] buf) { 877 int item = readUnsignedShort(index); 879 String s = strings[item]; 880 if (s != null) { 881 return s; 882 } 883 index = items[item]; 885 int utfLen = readUnsignedShort(index); 887 index += 2; 888 int endIndex = index + utfLen; 890 byte[] b = this.b; 891 int strLen = 0; 892 int c, d, e; 893 while (index < endIndex) { 894 c = b[index++] & 0xFF; 895 switch (c >> 4) { 896 case 0: 897 case 1: 898 case 2: 899 case 3: 900 case 4: 901 case 5: 902 case 6: 903 case 7: 904 buf[strLen++] = (char)c; 906 break; 907 case 12: 908 case 13: 909 d = b[index++]; 911 buf[strLen++] = (char)(((c & 0x1F) << 6) | (d & 0x3F)); 912 break; 913 default: 914 d = b[index++]; 916 e = b[index++]; 917 buf[strLen++] = 918 (char)(((c & 0x0F) << 12) | ((d & 0x3F) << 6) | (e & 0x3F)); 919 break; 920 } 921 } 922 s = new String (buf, 0, strLen); 923 strings[item] = s; 924 return s; 925 } 926 927 938 939 public String readClass (final int index, final char[] buf) { 940 return readUTF8(items[readUnsignedShort(index)], buf); 944 } 945 946 959 960 public Object readConst (final int item, final char[] buf) { 961 int index = items[item]; 962 switch (b[index - 1]) { 963 case ClassWriter.INT: 964 return new Integer (readInt(index)); 965 case ClassWriter.FLOAT: 966 return new Float (Float.intBitsToFloat(readInt(index))); 967 case ClassWriter.LONG: 968 return new Long (readLong(index)); 969 case ClassWriter.DOUBLE: 970 return new Double (Double.longBitsToDouble(readLong(index))); 971 case ClassWriter.CLASS: 972 String s = readUTF8(index, buf); 973 return Type.getType(s.charAt(0) == '[' ? s : "L" + s + ";"); 974 default: 976 return readUTF8(index, buf); 977 } 978 } 979 980 1004 1005 protected Attribute readAttribute ( 1006 final Attribute[] attrs, 1007 final String type, 1008 final int off, 1009 final int len, 1010 final char[] buf, 1011 final int codeOff, 1012 final Label[] labels) 1013 { 1014 for (int i = 0; i < attrs.length; ++i) { 1015 if (attrs[i].type.equals(type)) { 1016 return attrs[i].read(this, off, len, buf, codeOff, labels); 1017 } 1018 } 1019 return new Attribute(type); 1020 } 1021} 1022 | Popular Tags |