1 30 package org.objectweb.asm; 31 32 41 public class ClassWriter implements ClassVisitor { 42 43 46 final static int NOARG_INSN = 0; 47 48 51 final static int SBYTE_INSN = 1; 52 53 56 final static int SHORT_INSN = 2; 57 58 61 final static int VAR_INSN = 3; 62 63 66 final static int IMPLVAR_INSN = 4; 67 68 71 final static int TYPE_INSN = 5; 72 73 76 final static int FIELDORMETH_INSN = 6; 77 78 81 final static int ITFMETH_INSN = 7; 82 83 86 final static int LABEL_INSN = 8; 87 88 91 final static int LABELW_INSN = 9; 92 93 96 final static int LDC_INSN = 10; 97 98 101 final static int LDCW_INSN = 11; 102 103 106 final static int IINC_INSN = 12; 107 108 111 final static int TABL_INSN = 13; 112 113 116 final static int LOOK_INSN = 14; 117 118 121 final static int MANA_INSN = 15; 122 123 126 final static int WIDE_INSN = 16; 127 128 131 static byte[] TYPE; 132 133 136 final static int CLASS = 7; 137 138 141 final static int FIELD = 9; 142 143 146 final static int METH = 10; 147 148 151 final static int IMETH = 11; 152 153 156 final static int STR = 8; 157 158 161 final static int INT = 3; 162 163 166 final static int FLOAT = 4; 167 168 171 final static int LONG = 5; 172 173 176 final static int DOUBLE = 6; 177 178 181 final static int NAME_TYPE = 12; 182 183 186 final static int UTF8 = 1; 187 188 191 int version; 192 193 196 private short index; 197 198 201 private ByteVector pool; 202 203 206 private Item[] items; 207 208 211 private int threshold; 212 213 216 Item key; 217 218 221 Item key2; 222 223 226 Item key3; 227 228 231 private int access; 232 233 236 private int name; 237 238 241 private int signature; 242 243 247 private int superName; 248 249 252 private int interfaceCount; 253 254 259 private int[] interfaces; 260 261 265 private int sourceFile; 266 267 270 private ByteVector sourceDebug; 271 272 276 private int enclosingMethodOwner; 277 278 282 private int enclosingMethod; 283 284 287 private AnnotationWriter anns; 288 289 292 private AnnotationWriter ianns; 293 294 297 private Attribute attrs; 298 299 302 private int innerClassesCount; 303 304 307 private ByteVector innerClasses; 308 309 315 FieldWriter firstField; 316 317 323 FieldWriter lastField; 324 325 331 MethodWriter firstMethod; 332 333 339 MethodWriter lastMethod; 340 341 345 private boolean computeMaxs; 346 347 350 boolean checkAttributes; 351 352 356 359 static { 360 int i; 361 byte[] b = new byte[220]; 362 String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" 363 + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 364 + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA" 365 + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII"; 366 for (i = 0; i < b.length; ++i) { 367 b[i] = (byte) (s.charAt(i) - 'A'); 368 } 369 TYPE = b; 370 371 } 438 439 443 455 public ClassWriter(final boolean computeMaxs) { 456 this(computeMaxs, false); 457 } 458 459 474 public ClassWriter( 475 final boolean computeMaxs, 476 final boolean skipUnknownAttributes) 477 { 478 index = 1; 479 pool = new ByteVector(); 480 items = new Item[256]; 481 threshold = (int) (0.75d * items.length); 482 key = new Item(); 483 key2 = new Item(); 484 key3 = new Item(); 485 this.computeMaxs = computeMaxs; 486 this.checkAttributes = !skipUnknownAttributes; 487 } 488 489 493 public void visit( 494 final int version, 495 final int access, 496 final String name, 497 final String signature, 498 final String superName, 499 final String [] interfaces) 500 { 501 this.version = version; 502 this.access = access; 503 this.name = newClass(name); 504 if (signature != null) { 505 this.signature = newUTF8(signature); 506 } 507 this.superName = superName == null ? 0 : newClass(superName); 508 if (interfaces != null && interfaces.length > 0) { 509 interfaceCount = interfaces.length; 510 this.interfaces = new int[interfaceCount]; 511 for (int i = 0; i < interfaceCount; ++i) { 512 this.interfaces[i] = newClass(interfaces[i]); 513 } 514 } 515 } 516 517 public void visitSource(final String file, final String debug) { 518 if (file != null) { 519 sourceFile = newUTF8(file); 520 } 521 if (debug != null) { 522 sourceDebug = new ByteVector(); 523 sourceDebug.putUTF8(debug); 524 } 525 } 526 527 public void visitOuterClass( 528 final String owner, 529 final String name, 530 final String desc) 531 { 532 enclosingMethodOwner = newClass(owner); 533 if (name != null && desc != null) { 534 enclosingMethod = newNameType(name, desc); 535 } 536 } 537 538 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 539 ByteVector bv = new ByteVector(); 540 bv.putShort(newUTF8(desc)).putShort(0); 542 AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); 543 if (visible) { 544 aw.next = anns; 545 anns = aw; 546 } else { 547 aw.next = ianns; 548 ianns = aw; 549 } 550 return aw; 551 } 552 553 public void visitAttribute(final Attribute attr) { 554 attr.next = attrs; 555 attrs = attr; 556 } 557 558 public void visitInnerClass( 559 final String name, 560 final String outerName, 561 final String innerName, 562 final int access) 563 { 564 if (innerClasses == null) { 565 innerClasses = new ByteVector(); 566 } 567 ++innerClassesCount; 568 innerClasses.putShort(name == null ? 0 : newClass(name)); 569 innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); 570 innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); 571 innerClasses.putShort(access); 572 } 573 574 public FieldVisitor visitField( 575 final int access, 576 final String name, 577 final String desc, 578 final String signature, 579 final Object value) 580 { 581 return new FieldWriter(this, access, name, desc, signature, value); 582 } 583 584 public MethodVisitor visitMethod( 585 final int access, 586 final String name, 587 final String desc, 588 final String signature, 589 final String [] exceptions) 590 { 591 return new MethodWriter(this, 592 access, 593 name, 594 desc, 595 signature, 596 exceptions, 597 computeMaxs); 598 } 599 600 public void visitEnd() { 601 } 602 603 607 612 public byte[] toByteArray() { 613 int size = 24 + 2 * interfaceCount; 615 int nbFields = 0; 616 FieldWriter fb = firstField; 617 while (fb != null) { 618 ++nbFields; 619 size += fb.getSize(); 620 fb = fb.next; 621 } 622 int nbMethods = 0; 623 MethodWriter mb = firstMethod; 624 while (mb != null) { 625 ++nbMethods; 626 size += mb.getSize(); 627 mb = mb.next; 628 } 629 int attributeCount = 0; 630 if (signature != 0) { 631 ++attributeCount; 632 size += 8; 633 newUTF8("Signature"); 634 } 635 if (sourceFile != 0) { 636 ++attributeCount; 637 size += 8; 638 newUTF8("SourceFile"); 639 } 640 if (sourceDebug != null) { 641 ++attributeCount; 642 size += sourceDebug.length; 643 newUTF8("SourceDebugExtension"); 644 } 645 if (enclosingMethodOwner != 0) { 646 ++attributeCount; 647 size += 10; 648 newUTF8("EnclosingMethod"); 649 } 650 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 651 ++attributeCount; 652 size += 6; 653 newUTF8("Deprecated"); 654 } 655 if ((access & Opcodes.ACC_SYNTHETIC) != 0 656 && (version & 0xffff) < Opcodes.V1_5) 657 { 658 ++attributeCount; 659 size += 6; 660 newUTF8("Synthetic"); 661 } 662 if (version == Opcodes.V1_4) { 663 if ((access & Opcodes.ACC_ANNOTATION) != 0) { 664 ++attributeCount; 665 size += 6; 666 newUTF8("Annotation"); 667 } 668 if ((access & Opcodes.ACC_ENUM) != 0) { 669 ++attributeCount; 670 size += 6; 671 newUTF8("Enum"); 672 } 673 } 674 if (innerClasses != null) { 675 ++attributeCount; 676 size += 8 + innerClasses.length; 677 newUTF8("InnerClasses"); 678 } 679 if (anns != null) { 680 ++attributeCount; 681 size += 8 + anns.getSize(); 682 newUTF8("RuntimeVisibleAnnotations"); 683 } 684 if (ianns != null) { 685 ++attributeCount; 686 size += 8 + ianns.getSize(); 687 newUTF8("RuntimeInvisibleAnnotations"); 688 } 689 if (attrs != null) { 690 attributeCount += attrs.getCount(); 691 size += attrs.getSize(this, null, 0, -1, -1); 692 } 693 size += pool.length; 694 ByteVector out = new ByteVector(size); 697 out.putInt(0xCAFEBABE).putInt(version); 698 out.putShort(index).putByteArray(pool.data, 0, pool.length); 699 out.putShort(access).putShort(name).putShort(superName); 700 out.putShort(interfaceCount); 701 for (int i = 0; i < interfaceCount; ++i) { 702 out.putShort(interfaces[i]); 703 } 704 out.putShort(nbFields); 705 fb = firstField; 706 while (fb != null) { 707 fb.put(out); 708 fb = fb.next; 709 } 710 out.putShort(nbMethods); 711 mb = firstMethod; 712 while (mb != null) { 713 mb.put(out); 714 mb = mb.next; 715 } 716 out.putShort(attributeCount); 717 if (signature != 0) { 718 out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); 719 } 720 if (sourceFile != 0) { 721 out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); 722 } 723 if (sourceDebug != null) { 724 int len = sourceDebug.length; 725 out.putShort(newUTF8("SourceDebugExtension")).putInt(len); 726 out.putByteArray(sourceDebug.data, 0, len); 727 } 728 if (enclosingMethodOwner != 0) { 729 out.putShort(newUTF8("EnclosingMethod")).putInt(4); 730 out.putShort(enclosingMethodOwner).putShort(enclosingMethod); 731 } 732 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 733 out.putShort(newUTF8("Deprecated")).putInt(0); 734 } 735 if ((access & Opcodes.ACC_SYNTHETIC) != 0 736 && (version & 0xffff) < Opcodes.V1_5) 737 { 738 out.putShort(newUTF8("Synthetic")).putInt(0); 739 } 740 if (version == Opcodes.V1_4) { 741 if ((access & Opcodes.ACC_ANNOTATION) != 0) { 742 out.putShort(newUTF8("Annotation")).putInt(0); 743 } 744 if ((access & Opcodes.ACC_ENUM) != 0) { 745 out.putShort(newUTF8("Enum")).putInt(0); 746 } 747 } 748 if (innerClasses != null) { 749 out.putShort(newUTF8("InnerClasses")); 750 out.putInt(innerClasses.length + 2).putShort(innerClassesCount); 751 out.putByteArray(innerClasses.data, 0, innerClasses.length); 752 } 753 if (anns != null) { 754 out.putShort(newUTF8("RuntimeVisibleAnnotations")); 755 anns.put(out); 756 } 757 if (ianns != null) { 758 out.putShort(newUTF8("RuntimeInvisibleAnnotations")); 759 ianns.put(out); 760 } 761 if (attrs != null) { 762 attrs.put(this, null, 0, -1, -1, out); 763 } 764 return out.data; 765 } 766 767 771 781 Item newConstItem(final Object cst) { 782 if (cst instanceof Integer ) { 783 int val = ((Integer ) cst).intValue(); 784 return newInteger(val); 785 } else if (cst instanceof Byte ) { 786 int val = ((Byte ) cst).intValue(); 787 return newInteger(val); 788 } else if (cst instanceof Character ) { 789 int val = ((Character ) cst).charValue(); 790 return newInteger(val); 791 } else if (cst instanceof Short ) { 792 int val = ((Short ) cst).intValue(); 793 return newInteger(val); 794 } else if (cst instanceof Boolean ) { 795 int val = ((Boolean ) cst).booleanValue() ? 1 : 0; 796 return newInteger(val); 797 } else if (cst instanceof Float ) { 798 float val = ((Float ) cst).floatValue(); 799 return newFloat(val); 800 } else if (cst instanceof Long ) { 801 long val = ((Long ) cst).longValue(); 802 return newLong(val); 803 } else if (cst instanceof Double ) { 804 double val = ((Double ) cst).doubleValue(); 805 return newDouble(val); 806 } else if (cst instanceof String ) { 807 return newString((String ) cst); 808 } else if (cst instanceof Type) { 809 Type t = (Type) cst; 810 return newClassItem(t.getSort() == Type.OBJECT 811 ? t.getInternalName() 812 : t.getDescriptor()); 813 } else { 814 throw new IllegalArgumentException ("value " + cst); 815 } 816 } 817 818 830 public int newConst(final Object cst) { 831 return newConstItem(cst).index; 832 } 833 834 843 public int newUTF8(final String value) { 844 key.set('s', value, null, null); 845 Item result = get(key); 846 if (result == null) { 847 pool.putByte(UTF8).putUTF8(value); 848 result = new Item(index++, key); 849 put(result); 850 } 851 return result.index; 852 } 853 854 863 public int newClass(final String value) { 864 return newClassItem(value).index; 865 } 866 867 876 private Item newClassItem(final String value) { 877 key2.set('C', value, null, null); 878 Item result = get(key2); 879 if (result == null) { 880 pool.put12(CLASS, newUTF8(value)); 881 result = new Item(index++, key2); 882 put(result); 883 } 884 return result; 885 } 886 887 898 public int newField(final String owner, final String name, final String desc) 899 { 900 key3.set('G', owner, name, desc); 901 Item result = get(key3); 902 if (result == null) { 903 put122(FIELD, newClass(owner), newNameType(name, desc)); 904 result = new Item(index++, key3); 905 put(result); 906 } 907 return result.index; 908 } 909 910 920 Item newMethodItem( 921 final String owner, 922 final String name, 923 final String desc, 924 final boolean itf) 925 { 926 key3.set(itf ? 'N' : 'M', owner, name, desc); 927 Item result = get(key3); 928 if (result == null) { 929 put122(itf ? IMETH : METH, newClass(owner), newNameType(name, desc)); 930 result = new Item(index++, key3); 931 put(result); 932 } 933 return result; 934 } 935 936 948 public int newMethod( 949 final String owner, 950 final String name, 951 final String desc, 952 final boolean itf) 953 { 954 return newMethodItem(owner, name, desc, itf).index; 955 } 956 957 964 Item newInteger(final int value) { 965 key.set(value); 966 Item result = get(key); 967 if (result == null) { 968 pool.putByte(INT).putInt(value); 969 result = new Item(index++, key); 970 put(result); 971 } 972 return result; 973 } 974 975 982 Item newFloat(final float value) { 983 key.set(value); 984 Item result = get(key); 985 if (result == null) { 986 pool.putByte(FLOAT).putInt(Float.floatToIntBits(value)); 987 result = new Item(index++, key); 988 put(result); 989 } 990 return result; 991 } 992 993 1000 Item newLong(final long value) { 1001 key.set(value); 1002 Item result = get(key); 1003 if (result == null) { 1004 pool.putByte(LONG).putLong(value); 1005 result = new Item(index, key); 1006 put(result); 1007 index += 2; 1008 } 1009 return result; 1010 } 1011 1012 1019 Item newDouble(final double value) { 1020 key.set(value); 1021 Item result = get(key); 1022 if (result == null) { 1023 pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value)); 1024 result = new Item(index, key); 1025 put(result); 1026 index += 2; 1027 } 1028 return result; 1029 } 1030 1031 1038 private Item newString(final String value) { 1039 key2.set('S', value, null, null); 1040 Item result = get(key2); 1041 if (result == null) { 1042 pool.put12(STR, newUTF8(value)); 1043 result = new Item(index++, key2); 1044 put(result); 1045 } 1046 return result; 1047 } 1048 1049 1059 public int newNameType(final String name, final String desc) { 1060 key2.set('T', name, desc, null); 1061 Item result = get(key2); 1062 if (result == null) { 1063 put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); 1064 result = new Item(index++, key2); 1065 put(result); 1066 } 1067 return result.index; 1068 } 1069 1070 1078 private Item get(final Item key) { 1079 int h = key.hashCode; 1080 Item i = items[h % items.length]; 1081 while (i != null) { 1082 if (i.hashCode == h && key.isEqualTo(i)) { 1083 return i; 1084 } 1085 i = i.next; 1086 } 1087 return null; 1088 } 1089 1090 1096 private void put(final Item i) { 1097 if (index > threshold) { 1098 Item[] newItems = new Item[items.length * 2 + 1]; 1099 for (int l = items.length - 1; l >= 0; --l) { 1100 Item j = items[l]; 1101 while (j != null) { 1102 int index = j.hashCode % newItems.length; 1103 Item k = j.next; 1104 j.next = newItems[index]; 1105 newItems[index] = j; 1106 j = k; 1107 } 1108 } 1109 items = newItems; 1110 threshold = (int) (items.length * 0.75); 1111 } 1112 int index = i.hashCode % items.length; 1113 i.next = items[index]; 1114 items[index] = i; 1115 } 1116 1117 1124 private void put122(final int b, final int s1, final int s2) { 1125 pool.put12(b, s1).putShort(s2); 1126 } 1127} 1128
| Popular Tags
|