1 30 package com.sleepycat.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 ClassReader cr; 192 193 196 int version; 197 198 201 int index; 202 203 206 ByteVector pool; 207 208 211 Item[] items; 212 213 216 int threshold; 217 218 221 Item key; 222 223 226 Item key2; 227 228 231 Item key3; 232 233 236 private int access; 237 238 241 private int name; 242 243 246 private int signature; 247 248 252 private int superName; 253 254 257 private int interfaceCount; 258 259 264 private int[] interfaces; 265 266 270 private int sourceFile; 271 272 275 private ByteVector sourceDebug; 276 277 281 private int enclosingMethodOwner; 282 283 287 private int enclosingMethod; 288 289 292 private AnnotationWriter anns; 293 294 297 private AnnotationWriter ianns; 298 299 302 private Attribute attrs; 303 304 307 private int innerClassesCount; 308 309 312 private ByteVector innerClasses; 313 314 320 FieldWriter firstField; 321 322 328 FieldWriter lastField; 329 330 336 MethodWriter firstMethod; 337 338 344 MethodWriter lastMethod; 345 346 350 private boolean computeMaxs; 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 473 public ClassWriter( 474 final boolean computeMaxs, 475 final boolean skipUnknownAttributes) 476 { 477 index = 1; 478 pool = new ByteVector(); 479 items = new Item[256]; 480 threshold = (int) (0.75d * items.length); 481 key = new Item(); 482 key2 = new Item(); 483 key3 = new Item(); 484 this.computeMaxs = computeMaxs; 485 } 486 487 517 public ClassWriter( 518 final ClassReader classReader, 519 final boolean computeMaxs) 520 { 521 this(computeMaxs, false); 522 classReader.copyPool(this); 523 this.cr = classReader; 524 } 525 526 530 public void visit( 531 final int version, 532 final int access, 533 final String name, 534 final String signature, 535 final String superName, 536 final String [] interfaces) 537 { 538 this.version = version; 539 this.access = access; 540 this.name = newClass(name); 541 if (signature != null) { 542 this.signature = newUTF8(signature); 543 } 544 this.superName = superName == null ? 0 : newClass(superName); 545 if (interfaces != null && interfaces.length > 0) { 546 interfaceCount = interfaces.length; 547 this.interfaces = new int[interfaceCount]; 548 for (int i = 0; i < interfaceCount; ++i) { 549 this.interfaces[i] = newClass(interfaces[i]); 550 } 551 } 552 } 553 554 public void visitSource(final String file, final String debug) { 555 if (file != null) { 556 sourceFile = newUTF8(file); 557 } 558 if (debug != null) { 559 sourceDebug = new ByteVector().putUTF8(debug); 560 } 561 } 562 563 public void visitOuterClass( 564 final String owner, 565 final String name, 566 final String desc) 567 { 568 enclosingMethodOwner = newClass(owner); 569 if (name != null && desc != null) { 570 enclosingMethod = newNameType(name, desc); 571 } 572 } 573 574 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 575 ByteVector bv = new ByteVector(); 576 bv.putShort(newUTF8(desc)).putShort(0); 578 AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2); 579 if (visible) { 580 aw.next = anns; 581 anns = aw; 582 } else { 583 aw.next = ianns; 584 ianns = aw; 585 } 586 return aw; 587 } 588 589 public void visitAttribute(final Attribute attr) { 590 attr.next = attrs; 591 attrs = attr; 592 } 593 594 public void visitInnerClass( 595 final String name, 596 final String outerName, 597 final String innerName, 598 final int access) 599 { 600 if (innerClasses == null) { 601 innerClasses = new ByteVector(); 602 } 603 ++innerClassesCount; 604 innerClasses.putShort(name == null ? 0 : newClass(name)); 605 innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); 606 innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); 607 innerClasses.putShort(access); 608 } 609 610 public FieldVisitor visitField( 611 final int access, 612 final String name, 613 final String desc, 614 final String signature, 615 final Object value) 616 { 617 return new FieldWriter(this, access, name, desc, signature, value); 618 } 619 620 public MethodVisitor visitMethod( 621 final int access, 622 final String name, 623 final String desc, 624 final String signature, 625 final String [] exceptions) 626 { 627 return new MethodWriter(this, 628 access, 629 name, 630 desc, 631 signature, 632 exceptions, 633 computeMaxs); 634 } 635 636 public void visitEnd() { 637 } 638 639 643 648 public byte[] toByteArray() { 649 int size = 24 + 2 * interfaceCount; 651 int nbFields = 0; 652 FieldWriter fb = firstField; 653 while (fb != null) { 654 ++nbFields; 655 size += fb.getSize(); 656 fb = fb.next; 657 } 658 int nbMethods = 0; 659 MethodWriter mb = firstMethod; 660 while (mb != null) { 661 ++nbMethods; 662 size += mb.getSize(); 663 mb = mb.next; 664 } 665 int attributeCount = 0; 666 if (signature != 0) { 667 ++attributeCount; 668 size += 8; 669 newUTF8("Signature"); 670 } 671 if (sourceFile != 0) { 672 ++attributeCount; 673 size += 8; 674 newUTF8("SourceFile"); 675 } 676 if (sourceDebug != null) { 677 ++attributeCount; 678 size += sourceDebug.length + 4; 679 newUTF8("SourceDebugExtension"); 680 } 681 if (enclosingMethodOwner != 0) { 682 ++attributeCount; 683 size += 10; 684 newUTF8("EnclosingMethod"); 685 } 686 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 687 ++attributeCount; 688 size += 6; 689 newUTF8("Deprecated"); 690 } 691 if ((access & Opcodes.ACC_SYNTHETIC) != 0 692 && (version & 0xffff) < Opcodes.V1_5) 693 { 694 ++attributeCount; 695 size += 6; 696 newUTF8("Synthetic"); 697 } 698 if (version == Opcodes.V1_4) { 699 if ((access & Opcodes.ACC_ANNOTATION) != 0) { 700 ++attributeCount; 701 size += 6; 702 newUTF8("Annotation"); 703 } 704 if ((access & Opcodes.ACC_ENUM) != 0) { 705 ++attributeCount; 706 size += 6; 707 newUTF8("Enum"); 708 } 709 } 710 if (innerClasses != null) { 711 ++attributeCount; 712 size += 8 + innerClasses.length; 713 newUTF8("InnerClasses"); 714 } 715 if (anns != null) { 716 ++attributeCount; 717 size += 8 + anns.getSize(); 718 newUTF8("RuntimeVisibleAnnotations"); 719 } 720 if (ianns != null) { 721 ++attributeCount; 722 size += 8 + ianns.getSize(); 723 newUTF8("RuntimeInvisibleAnnotations"); 724 } 725 if (attrs != null) { 726 attributeCount += attrs.getCount(); 727 size += attrs.getSize(this, null, 0, -1, -1); 728 } 729 size += pool.length; 730 ByteVector out = new ByteVector(size); 733 out.putInt(0xCAFEBABE).putInt(version); 734 out.putShort(index).putByteArray(pool.data, 0, pool.length); 735 out.putShort(access).putShort(name).putShort(superName); 736 out.putShort(interfaceCount); 737 for (int i = 0; i < interfaceCount; ++i) { 738 out.putShort(interfaces[i]); 739 } 740 out.putShort(nbFields); 741 fb = firstField; 742 while (fb != null) { 743 fb.put(out); 744 fb = fb.next; 745 } 746 out.putShort(nbMethods); 747 mb = firstMethod; 748 while (mb != null) { 749 mb.put(out); 750 mb = mb.next; 751 } 752 out.putShort(attributeCount); 753 if (signature != 0) { 754 out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); 755 } 756 if (sourceFile != 0) { 757 out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); 758 } 759 if (sourceDebug != null) { 760 int len = sourceDebug.length - 2; 761 out.putShort(newUTF8("SourceDebugExtension")).putInt(len); 762 out.putByteArray(sourceDebug.data, 2, len); 763 } 764 if (enclosingMethodOwner != 0) { 765 out.putShort(newUTF8("EnclosingMethod")).putInt(4); 766 out.putShort(enclosingMethodOwner).putShort(enclosingMethod); 767 } 768 if ((access & Opcodes.ACC_DEPRECATED) != 0) { 769 out.putShort(newUTF8("Deprecated")).putInt(0); 770 } 771 if ((access & Opcodes.ACC_SYNTHETIC) != 0 772 && (version & 0xffff) < Opcodes.V1_5) 773 { 774 out.putShort(newUTF8("Synthetic")).putInt(0); 775 } 776 if (version == Opcodes.V1_4) { 777 if ((access & Opcodes.ACC_ANNOTATION) != 0) { 778 out.putShort(newUTF8("Annotation")).putInt(0); 779 } 780 if ((access & Opcodes.ACC_ENUM) != 0) { 781 out.putShort(newUTF8("Enum")).putInt(0); 782 } 783 } 784 if (innerClasses != null) { 785 out.putShort(newUTF8("InnerClasses")); 786 out.putInt(innerClasses.length + 2).putShort(innerClassesCount); 787 out.putByteArray(innerClasses.data, 0, innerClasses.length); 788 } 789 if (anns != null) { 790 out.putShort(newUTF8("RuntimeVisibleAnnotations")); 791 anns.put(out); 792 } 793 if (ianns != null) { 794 out.putShort(newUTF8("RuntimeInvisibleAnnotations")); 795 ianns.put(out); 796 } 797 if (attrs != null) { 798 attrs.put(this, null, 0, -1, -1, out); 799 } 800 return out.data; 801 } 802 803 807 817 Item newConstItem(final Object cst) { 818 if (cst instanceof Integer ) { 819 int val = ((Integer ) cst).intValue(); 820 return newInteger(val); 821 } else if (cst instanceof Byte ) { 822 int val = ((Byte ) cst).intValue(); 823 return newInteger(val); 824 } else if (cst instanceof Character ) { 825 int val = ((Character ) cst).charValue(); 826 return newInteger(val); 827 } else if (cst instanceof Short ) { 828 int val = ((Short ) cst).intValue(); 829 return newInteger(val); 830 } else if (cst instanceof Boolean ) { 831 int val = ((Boolean ) cst).booleanValue() ? 1 : 0; 832 return newInteger(val); 833 } else if (cst instanceof Float ) { 834 float val = ((Float ) cst).floatValue(); 835 return newFloat(val); 836 } else if (cst instanceof Long ) { 837 long val = ((Long ) cst).longValue(); 838 return newLong(val); 839 } else if (cst instanceof Double ) { 840 double val = ((Double ) cst).doubleValue(); 841 return newDouble(val); 842 } else if (cst instanceof String ) { 843 return newString((String ) cst); 844 } else if (cst instanceof Type) { 845 Type t = (Type) cst; 846 return newClassItem(t.getSort() == Type.OBJECT 847 ? t.getInternalName() 848 : t.getDescriptor()); 849 } else { 850 throw new IllegalArgumentException ("value " + cst); 851 } 852 } 853 854 866 public int newConst(final Object cst) { 867 return newConstItem(cst).index; 868 } 869 870 879 public int newUTF8(final String value) { 880 key.set(UTF8, value, null, null); 881 Item result = get(key); 882 if (result == null) { 883 pool.putByte(UTF8).putUTF8(value); 884 result = new Item(index++, key); 885 put(result); 886 } 887 return result.index; 888 } 889 890 899 public int newClass(final String value) { 900 return newClassItem(value).index; 901 } 902 903 912 private Item newClassItem(final String value) { 913 key2.set(CLASS, value, null, null); 914 Item result = get(key2); 915 if (result == null) { 916 pool.put12(CLASS, newUTF8(value)); 917 result = new Item(index++, key2); 918 put(result); 919 } 920 return result; 921 } 922 923 934 public int newField(final String owner, final String name, final String desc) 935 { 936 key3.set(FIELD, owner, name, desc); 937 Item result = get(key3); 938 if (result == null) { 939 put122(FIELD, newClass(owner), newNameType(name, desc)); 940 result = new Item(index++, key3); 941 put(result); 942 } 943 return result.index; 944 } 945 946 956 Item newMethodItem( 957 final String owner, 958 final String name, 959 final String desc, 960 final boolean itf) 961 { 962 int type = itf ? IMETH : METH; 963 key3.set(type, owner, name, desc); 964 Item result = get(key3); 965 if (result == null) { 966 put122(type, newClass(owner), newNameType(name, desc)); 967 result = new Item(index++, key3); 968 put(result); 969 } 970 return result; 971 } 972 973 985 public int newMethod( 986 final String owner, 987 final String name, 988 final String desc, 989 final boolean itf) 990 { 991 return newMethodItem(owner, name, desc, itf).index; 992 } 993 994 1001 Item newInteger(final int value) { 1002 key.set(value); 1003 Item result = get(key); 1004 if (result == null) { 1005 pool.putByte(INT).putInt(value); 1006 result = new Item(index++, key); 1007 put(result); 1008 } 1009 return result; 1010 } 1011 1012 1019 Item newFloat(final float value) { 1020 key.set(value); 1021 Item result = get(key); 1022 if (result == null) { 1023 pool.putByte(FLOAT).putInt(Float.floatToIntBits(value)); 1024 result = new Item(index++, key); 1025 put(result); 1026 } 1027 return result; 1028 } 1029 1030 1037 Item newLong(final long value) { 1038 key.set(value); 1039 Item result = get(key); 1040 if (result == null) { 1041 pool.putByte(LONG).putLong(value); 1042 result = new Item(index, key); 1043 put(result); 1044 index += 2; 1045 } 1046 return result; 1047 } 1048 1049 1056 Item newDouble(final double value) { 1057 key.set(value); 1058 Item result = get(key); 1059 if (result == null) { 1060 pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value)); 1061 result = new Item(index, key); 1062 put(result); 1063 index += 2; 1064 } 1065 return result; 1066 } 1067 1068 1075 private Item newString(final String value) { 1076 key2.set(STR, value, null, null); 1077 Item result = get(key2); 1078 if (result == null) { 1079 pool.put12(STR, newUTF8(value)); 1080 result = new Item(index++, key2); 1081 put(result); 1082 } 1083 return result; 1084 } 1085 1086 1096 public int newNameType(final String name, final String desc) { 1097 key2.set(NAME_TYPE, name, desc, null); 1098 Item result = get(key2); 1099 if (result == null) { 1100 put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); 1101 result = new Item(index++, key2); 1102 put(result); 1103 } 1104 return result.index; 1105 } 1106 1107 1115 private Item get(final Item key) { 1116 Item i = items[key.hashCode % items.length]; 1117 while (i != null && !key.isEqualTo(i)) { 1118 i = i.next; 1119 } 1120 return i; 1121 } 1122 1123 1129 private void put(final Item i) { 1130 if (index > threshold) { 1131 int ll = items.length; 1132 int nl = ll * 2 + 1; 1133 Item[] newItems = new Item[nl]; 1134 for (int l = ll - 1; l >= 0; --l) { 1135 Item j = items[l]; 1136 while (j != null) { 1137 int index = j.hashCode % newItems.length; 1138 Item k = j.next; 1139 j.next = newItems[index]; 1140 newItems[index] = j; 1141 j = k; 1142 } 1143 } 1144 items = newItems; 1145 threshold = (int) (nl * 0.75); 1146 } 1147 int index = i.hashCode % items.length; 1148 i.next = items[index]; 1149 items[index] = i; 1150 } 1151 1152 1159 private void put122(final int b, final int s1, final int s2) { 1160 pool.put12(b, s1).putShort(s2); 1161 } 1162} 1163 | Popular Tags |