1 30 package org.objectweb.asm.commons; 31 32 import java.util.ArrayList ; 33 import java.util.Arrays ; 34 import java.util.List ; 35 36 import org.objectweb.asm.ClassVisitor; 37 import org.objectweb.asm.Label; 38 import org.objectweb.asm.MethodVisitor; 39 import org.objectweb.asm.Opcodes; 40 import org.objectweb.asm.Type; 41 42 82 public class GeneratorAdapter extends LocalVariablesSorter { 83 84 private final static Type BYTE_TYPE = Type.getType("Ljava/lang/Byte;"); 85 86 private final static Type BOOLEAN_TYPE = Type.getType("Ljava/lang/Boolean;"); 87 88 private final static Type SHORT_TYPE = Type.getType("Ljava/lang/Short;"); 89 90 private final static Type CHARACTER_TYPE = Type.getType("Ljava/lang/Character;"); 91 92 private final static Type INTEGER_TYPE = Type.getType("Ljava/lang/Integer;"); 93 94 private final static Type FLOAT_TYPE = Type.getType("Ljava/lang/Float;"); 95 96 private final static Type LONG_TYPE = Type.getType("Ljava/lang/Long;"); 97 98 private final static Type DOUBLE_TYPE = Type.getType("Ljava/lang/Double;"); 99 100 private final static Type NUMBER_TYPE = Type.getType("Ljava/lang/Number;"); 101 102 private final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;"); 103 104 private final static Method BOOLEAN_VALUE = Method.getMethod("boolean booleanValue()"); 105 106 private final static Method CHAR_VALUE = Method.getMethod("char charValue()"); 107 108 private final static Method INT_VALUE = Method.getMethod("int intValue()"); 109 110 private final static Method FLOAT_VALUE = Method.getMethod("float floatValue()"); 111 112 private final static Method LONG_VALUE = Method.getMethod("long longValue()"); 113 114 private final static Method DOUBLE_VALUE = Method.getMethod("double doubleValue()"); 115 116 119 public final static int ADD = Opcodes.IADD; 120 121 124 public final static int SUB = Opcodes.ISUB; 125 126 129 public final static int MUL = Opcodes.IMUL; 130 131 134 public final static int DIV = Opcodes.IDIV; 135 136 139 public final static int REM = Opcodes.IREM; 140 141 144 public final static int NEG = Opcodes.INEG; 145 146 149 public final static int SHL = Opcodes.ISHL; 150 151 154 public final static int SHR = Opcodes.ISHR; 155 156 159 public final static int USHR = Opcodes.IUSHR; 160 161 164 public final static int AND = Opcodes.IAND; 165 166 169 public final static int OR = Opcodes.IOR; 170 171 174 public final static int XOR = Opcodes.IXOR; 175 176 179 public final static int EQ = Opcodes.IFEQ; 180 181 184 public final static int NE = Opcodes.IFNE; 185 186 189 public final static int LT = Opcodes.IFLT; 190 191 194 public final static int GE = Opcodes.IFGE; 195 196 199 public final static int GT = Opcodes.IFGT; 200 201 204 public final static int LE = Opcodes.IFLE; 205 206 209 private final int access; 210 211 214 private final Type returnType; 215 216 219 private final Type[] argumentTypes; 220 221 224 private final List localTypes; 225 226 233 public GeneratorAdapter( 234 final int access, 235 final Method method, 236 final MethodVisitor mv) 237 { 238 super(access, method.getDescriptor(), mv); 239 this.access = access; 240 this.returnType = method.getReturnType(); 241 this.argumentTypes = method.getArgumentTypes(); 242 this.localTypes = new ArrayList (); 243 } 244 245 256 public GeneratorAdapter( 257 final int access, 258 final Method method, 259 final String signature, 260 final Type[] exceptions, 261 final ClassVisitor cv) 262 { 263 this(access, method, cv.visitMethod(access, 264 method.getName(), 265 method.getDescriptor(), 266 signature, 267 getInternalNames(exceptions))); 268 } 269 270 276 private static String [] getInternalNames(final Type[] types) { 277 if (types == null) { 278 return null; 279 } 280 String [] names = new String [types.length]; 281 for (int i = 0; i < names.length; ++i) { 282 names[i] = types[i].getInternalName(); 283 } 284 return names; 285 } 286 287 291 296 public void push(final boolean value) { 297 push(value ? 1 : 0); 298 } 299 300 305 public void push(final int value) { 306 if (value >= -1 && value <= 5) { 307 mv.visitInsn(Opcodes.ICONST_0 + value); 308 } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { 309 mv.visitIntInsn(Opcodes.BIPUSH, value); 310 } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { 311 mv.visitIntInsn(Opcodes.SIPUSH, value); 312 } else { 313 mv.visitLdcInsn(new Integer (value)); 314 } 315 } 316 317 322 public void push(final long value) { 323 if (value == 0L || value == 1L) { 324 mv.visitInsn(Opcodes.LCONST_0 + (int) value); 325 } else { 326 mv.visitLdcInsn(new Long (value)); 327 } 328 } 329 330 335 public void push(final float value) { 336 int bits = Float.floatToIntBits(value); 337 if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { mv.visitInsn(Opcodes.FCONST_0 + (int) value); 339 } else { 340 mv.visitLdcInsn(new Float (value)); 341 } 342 } 343 344 349 public void push(final double value) { 350 long bits = Double.doubleToLongBits(value); 351 if (bits == 0L || bits == 0x3ff0000000000000L) { mv.visitInsn(Opcodes.DCONST_0 + (int) value); 353 } else { 354 mv.visitLdcInsn(new Double (value)); 355 } 356 } 357 358 363 public void push(final String value) { 364 if (value == null) { 365 mv.visitInsn(Opcodes.ACONST_NULL); 366 } else { 367 mv.visitLdcInsn(value); 368 } 369 } 370 371 376 public void push(final Type value) { 377 if (value == null) { 378 mv.visitInsn(Opcodes.ACONST_NULL); 379 } else { 380 mv.visitLdcInsn(value); 381 } 382 } 383 384 388 396 private int getArgIndex(final int arg) { 397 int index = ((access & Opcodes.ACC_STATIC) == 0 ? 1 : 0); 398 for (int i = 0; i < arg; i++) { 399 index += argumentTypes[i].getSize(); 400 } 401 return index; 402 } 403 404 410 private void loadInsn(final Type type, final int index) { 411 mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index); 412 } 413 414 421 private void storeInsn(final Type type, final int index) { 422 mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index); 423 } 424 425 428 public void loadThis() { 429 if ((access & Opcodes.ACC_STATIC) != 0) { 430 throw new IllegalStateException ("no 'this' pointer within static method"); 431 } 432 mv.visitVarInsn(Opcodes.ALOAD, 0); 433 } 434 435 440 public void loadArg(final int arg) { 441 loadInsn(argumentTypes[arg], getArgIndex(arg)); 442 } 443 444 451 public void loadArgs(final int arg, final int count) { 452 int index = getArgIndex(arg); 453 for (int i = 0; i < count; ++i) { 454 Type t = argumentTypes[arg + i]; 455 loadInsn(t, index); 456 index += t.getSize(); 457 } 458 } 459 460 463 public void loadArgs() { 464 loadArgs(0, argumentTypes.length); 465 } 466 467 471 public void loadArgArray() { 472 push(argumentTypes.length); 473 newArray(OBJECT_TYPE); 474 for (int i = 0; i < argumentTypes.length; i++) { 475 dup(); 476 push(i); 477 loadArg(i); 478 box(argumentTypes[i]); 479 arrayStore(OBJECT_TYPE); 480 } 481 } 482 483 489 public void storeArg(final int arg) { 490 storeInsn(argumentTypes[arg], getArgIndex(arg)); 491 } 492 493 497 503 public int newLocal(final Type type) { 504 int local = super.newLocal(type.getSize()); 505 setLocalType(local, type); 506 return local; 507 } 508 509 516 public Type getLocalType(final int local) { 517 return (Type) localTypes.get(local - firstLocal); 518 } 519 520 527 private void setLocalType(final int local, final Type type) { 528 int index = local - firstLocal; 529 while (localTypes.size() < index + 1) 530 localTypes.add(null); 531 localTypes.set(index, type); 532 } 533 534 540 public void loadLocal(final int local) { 541 loadInsn(getLocalType(local), local); 542 } 543 544 550 public void loadLocal(final int local, final Type type) { 551 setLocalType(local, type); 552 loadInsn(type, local); 553 } 554 555 562 public void storeLocal(final int local) { 563 storeInsn(getLocalType(local), local); 564 } 565 566 573 public void storeLocal(final int local, final Type type) { 574 setLocalType(local, type); 575 storeInsn(type, local); 576 } 577 578 583 public void arrayLoad(final Type type) { 584 mv.visitInsn(type.getOpcode(Opcodes.IALOAD)); 585 } 586 587 592 public void arrayStore(final Type type) { 593 mv.visitInsn(type.getOpcode(Opcodes.IASTORE)); 594 } 595 596 600 603 public void pop() { 604 mv.visitInsn(Opcodes.POP); 605 } 606 607 610 public void pop2() { 611 mv.visitInsn(Opcodes.POP2); 612 } 613 614 617 public void dup() { 618 mv.visitInsn(Opcodes.DUP); 619 } 620 621 624 public void dup2() { 625 mv.visitInsn(Opcodes.DUP2); 626 } 627 628 631 public void dupX1() { 632 mv.visitInsn(Opcodes.DUP_X1); 633 } 634 635 638 public void dupX2() { 639 mv.visitInsn(Opcodes.DUP_X2); 640 } 641 642 645 public void dup2X1() { 646 mv.visitInsn(Opcodes.DUP2_X1); 647 } 648 649 652 public void dup2X2() { 653 mv.visitInsn(Opcodes.DUP2_X2); 654 } 655 656 659 public void swap() { 660 mv.visitInsn(Opcodes.SWAP); 661 } 662 663 669 public void swap(final Type prev, final Type type) { 670 if (type.getSize() == 1) { 671 if (prev.getSize() == 1) { 672 swap(); } else { 674 dupX2(); 675 pop(); 676 } 677 } else { 678 if (prev.getSize() == 1) { 679 dup2X1(); 680 pop2(); 681 } else { 682 dup2X2(); 683 pop2(); 684 } 685 } 686 } 687 688 692 700 public void math(final int op, final Type type) { 701 mv.visitInsn(type.getOpcode(op)); 702 } 703 704 708 public void not() { 709 mv.visitInsn(Opcodes.ICONST_1); 710 mv.visitInsn(Opcodes.IXOR); 711 } 712 713 719 public void iinc(final int local, final int amount) { 720 mv.visitIincInsn(local, amount); 721 } 722 723 730 public void cast(final Type from, final Type to) { 731 if (from != to) { 732 if (from == Type.DOUBLE_TYPE) { 733 if (to == Type.FLOAT_TYPE) { 734 mv.visitInsn(Opcodes.D2F); 735 } else if (to == Type.LONG_TYPE) { 736 mv.visitInsn(Opcodes.D2L); 737 } else { 738 mv.visitInsn(Opcodes.D2I); 739 cast(Type.INT_TYPE, to); 740 } 741 } else if (from == Type.FLOAT_TYPE) { 742 if (to == Type.DOUBLE_TYPE) { 743 mv.visitInsn(Opcodes.F2D); 744 } else if (to == Type.LONG_TYPE) { 745 mv.visitInsn(Opcodes.F2L); 746 } else { 747 mv.visitInsn(Opcodes.F2I); 748 cast(Type.INT_TYPE, to); 749 } 750 } else if (from == Type.LONG_TYPE) { 751 if (to == Type.DOUBLE_TYPE) { 752 mv.visitInsn(Opcodes.L2D); 753 } else if (to == Type.FLOAT_TYPE) { 754 mv.visitInsn(Opcodes.L2F); 755 } else { 756 mv.visitInsn(Opcodes.L2I); 757 cast(Type.INT_TYPE, to); 758 } 759 } else { 760 if (to == Type.BYTE_TYPE) { 761 mv.visitInsn(Opcodes.I2B); 762 } else if (to == Type.CHAR_TYPE) { 763 mv.visitInsn(Opcodes.I2C); 764 } else if (to == Type.DOUBLE_TYPE) { 765 mv.visitInsn(Opcodes.I2D); 766 } else if (to == Type.FLOAT_TYPE) { 767 mv.visitInsn(Opcodes.I2F); 768 } else if (to == Type.LONG_TYPE) { 769 mv.visitInsn(Opcodes.I2L); 770 } else if (to == Type.SHORT_TYPE) { 771 mv.visitInsn(Opcodes.I2S); 772 } 773 } 774 } 775 } 776 777 781 787 public void box(final Type type) { 788 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 789 return; 790 } 791 if (type == Type.VOID_TYPE) { 792 push((String ) null); 793 } else { 794 Type boxed = type; 795 switch (type.getSort()) { 796 case Type.BYTE: 797 boxed = BYTE_TYPE; 798 break; 799 case Type.BOOLEAN: 800 boxed = BOOLEAN_TYPE; 801 break; 802 case Type.SHORT: 803 boxed = SHORT_TYPE; 804 break; 805 case Type.CHAR: 806 boxed = CHARACTER_TYPE; 807 break; 808 case Type.INT: 809 boxed = INTEGER_TYPE; 810 break; 811 case Type.FLOAT: 812 boxed = FLOAT_TYPE; 813 break; 814 case Type.LONG: 815 boxed = LONG_TYPE; 816 break; 817 case Type.DOUBLE: 818 boxed = DOUBLE_TYPE; 819 break; 820 } 821 newInstance(boxed); 822 if (type.getSize() == 2) { 823 dupX2(); 825 dupX2(); 826 pop(); 827 } else { 828 dupX1(); 830 swap(); 831 } 832 invokeConstructor(boxed, new Method("<init>", 833 Type.VOID_TYPE, 834 new Type[] { type })); 835 } 836 } 837 838 844 public void unbox(final Type type) { 845 Type t = NUMBER_TYPE; 846 Method sig = null; 847 switch (type.getSort()) { 848 case Type.VOID: 849 return; 850 case Type.CHAR: 851 t = CHARACTER_TYPE; 852 sig = CHAR_VALUE; 853 break; 854 case Type.BOOLEAN: 855 t = BOOLEAN_TYPE; 856 sig = BOOLEAN_VALUE; 857 break; 858 case Type.DOUBLE: 859 sig = DOUBLE_VALUE; 860 break; 861 case Type.FLOAT: 862 sig = FLOAT_VALUE; 863 break; 864 case Type.LONG: 865 sig = LONG_VALUE; 866 break; 867 case Type.INT: 868 case Type.SHORT: 869 case Type.BYTE: 870 sig = INT_VALUE; 871 } 872 if (sig == null) { 873 checkCast(type); 874 } else { 875 checkCast(t); 876 invokeVirtual(t, sig); 877 } 878 } 879 880 884 889 public Label newLabel() { 890 return new Label(); 891 } 892 893 898 public void mark(final Label label) { 899 mv.visitLabel(label); 900 } 901 902 907 public Label mark() { 908 Label label = new Label(); 909 mv.visitLabel(label); 910 return label; 911 } 912 913 922 public void ifCmp(final Type type, final int mode, final Label label) { 923 int intOp = -1; 924 int jumpMode = mode; 925 switch (mode) { 926 case GE: 927 jumpMode = LT; 928 break; 929 case LE: 930 jumpMode = GT; 931 break; 932 } 933 switch (type.getSort()) { 934 case Type.LONG: 935 mv.visitInsn(Opcodes.LCMP); 936 break; 937 case Type.DOUBLE: 938 mv.visitInsn(Opcodes.DCMPG); 939 break; 940 case Type.FLOAT: 941 mv.visitInsn(Opcodes.FCMPG); 942 break; 943 case Type.ARRAY: 944 case Type.OBJECT: 945 switch (mode) { 946 case EQ: 947 mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label); 948 return; 949 case NE: 950 mv.visitJumpInsn(Opcodes.IF_ACMPNE, label); 951 return; 952 } 953 throw new IllegalArgumentException ("Bad comparison for type " 954 + type); 955 default: 956 switch (mode) { 957 case EQ: 958 intOp = Opcodes.IF_ICMPEQ; 959 break; 960 case NE: 961 intOp = Opcodes.IF_ICMPNE; 962 break; 963 case GE: 964 intOp = Opcodes.IF_ICMPGE; 965 break; 966 case LT: 967 intOp = Opcodes.IF_ICMPLT; 968 break; 969 case LE: 970 intOp = Opcodes.IF_ICMPLE; 971 break; 972 case GT: 973 intOp = Opcodes.IF_ICMPGT; 974 break; 975 } 976 mv.visitJumpInsn(intOp, label); 977 return; 978 } 979 mv.visitJumpInsn(jumpMode, label); 980 } 981 982 990 public void ifICmp(final int mode, final Label label) { 991 ifCmp(Type.INT_TYPE, mode, label); 992 } 993 994 1002 public void ifZCmp(final int mode, final Label label) { 1003 mv.visitJumpInsn(mode, label); 1004 } 1005 1006 1012 public void ifNull(final Label label) { 1013 mv.visitJumpInsn(Opcodes.IFNULL, label); 1014 } 1015 1016 1022 public void ifNonNull(final Label label) { 1023 mv.visitJumpInsn(Opcodes.IFNONNULL, label); 1024 } 1025 1026 1031 public void goTo(final Label label) { 1032 mv.visitJumpInsn(Opcodes.GOTO, label); 1033 } 1034 1035 1041 public void ret(final int local) { 1042 mv.visitVarInsn(Opcodes.RET, local); 1043 } 1044 1045 1051 public void tableSwitch( 1052 final int[] keys, 1053 final TableSwitchGenerator generator) 1054 { 1055 float density; 1056 if (keys.length == 0) { 1057 density = 0; 1058 } else { 1059 density = (float) keys.length 1060 / (keys[keys.length - 1] - keys[0] + 1); 1061 } 1062 tableSwitch(keys, generator, density >= 0.5f); 1063 } 1064 1065 1073 public void tableSwitch( 1074 final int[] keys, 1075 final TableSwitchGenerator generator, 1076 final boolean useTable) 1077 { 1078 for (int i = 1; i < keys.length; ++i) { 1079 if (keys[i] < keys[i - 1]) { 1080 throw new IllegalArgumentException ("keys must be sorted ascending"); 1081 } 1082 } 1083 Label def = newLabel(); 1084 Label end = newLabel(); 1085 if (keys.length > 0) { 1086 int len = keys.length; 1087 int min = keys[0]; 1088 int max = keys[len - 1]; 1089 int range = max - min + 1; 1090 if (useTable) { 1091 Label[] labels = new Label[range]; 1092 Arrays.fill(labels, def); 1093 for (int i = 0; i < len; ++i) { 1094 labels[keys[i] - min] = newLabel(); 1095 } 1096 mv.visitTableSwitchInsn(min, max, def, labels); 1097 for (int i = 0; i < range; ++i) { 1098 Label label = labels[i]; 1099 if (label != def) { 1100 mark(label); 1101 generator.generateCase(i + min, end); 1102 } 1103 } 1104 } else { 1105 Label[] labels = new Label[len]; 1106 for (int i = 0; i < len; ++i) { 1107 labels[i] = newLabel(); 1108 } 1109 mv.visitLookupSwitchInsn(def, keys, labels); 1110 for (int i = 0; i < len; ++i) { 1111 mark(labels[i]); 1112 generator.generateCase(keys[i], end); 1113 } 1114 } 1115 } 1116 mark(def); 1117 generator.generateDefault(); 1118 mark(end); 1119 } 1120 1121 1124 public void returnValue() { 1125 mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); 1126 } 1127 1128 1132 1140 private void fieldInsn( 1141 final int opcode, 1142 final Type ownerType, 1143 final String name, 1144 final Type fieldType) 1145 { 1146 mv.visitFieldInsn(opcode, 1147 ownerType.getInternalName(), 1148 name, 1149 fieldType.getDescriptor()); 1150 } 1151 1152 1160 public void getStatic(final Type owner, final String name, final Type type) 1161 { 1162 fieldInsn(Opcodes.GETSTATIC, owner, name, type); 1163 } 1164 1165 1172 public void putStatic(final Type owner, final String name, final Type type) 1173 { 1174 fieldInsn(Opcodes.PUTSTATIC, owner, name, type); 1175 } 1176 1177 1185 public void getField(final Type owner, final String name, final Type type) { 1186 fieldInsn(Opcodes.GETFIELD, owner, name, type); 1187 } 1188 1189 1197 public void putField(final Type owner, final String name, final Type type) { 1198 fieldInsn(Opcodes.PUTFIELD, owner, name, type); 1199 } 1200 1201 1205 1212 private void invokeInsn( 1213 final int opcode, 1214 final Type type, 1215 final Method method) 1216 { 1217 String owner = type.getSort() == Type.ARRAY 1218 ? type.getDescriptor() 1219 : type.getInternalName(); 1220 mv.visitMethodInsn(opcode, 1221 owner, 1222 method.getName(), 1223 method.getDescriptor()); 1224 } 1225 1226 1232 public void invokeVirtual(final Type owner, final Method method) { 1233 invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method); 1234 } 1235 1236 1242 public void invokeConstructor(final Type type, final Method method) { 1243 invokeInsn(Opcodes.INVOKESPECIAL, type, method); 1244 } 1245 1246 1252 public void invokeStatic(final Type owner, final Method method) { 1253 invokeInsn(Opcodes.INVOKESTATIC, owner, method); 1254 } 1255 1256 1262 public void invokeInterface(final Type owner, final Method method) { 1263 invokeInsn(Opcodes.INVOKEINTERFACE, owner, method); 1264 } 1265 1266 1270 1276 private void typeInsn(final int opcode, final Type type) { 1277 String desc; 1278 if (type.getSort() == Type.ARRAY) { 1279 desc = type.getDescriptor(); 1280 } else { 1281 desc = type.getInternalName(); 1282 } 1283 mv.visitTypeInsn(opcode, desc); 1284 } 1285 1286 1291 public void newInstance(final Type type) { 1292 typeInsn(Opcodes.NEW, type); 1293 } 1294 1295 1300 public void newArray(final Type type) { 1301 int typ; 1302 switch (type.getSort()) { 1303 case Type.BOOLEAN: 1304 typ = Opcodes.T_BOOLEAN; 1305 break; 1306 case Type.CHAR: 1307 typ = Opcodes.T_CHAR; 1308 break; 1309 case Type.BYTE: 1310 typ = Opcodes.T_BYTE; 1311 break; 1312 case Type.SHORT: 1313 typ = Opcodes.T_SHORT; 1314 break; 1315 case Type.INT: 1316 typ = Opcodes.T_INT; 1317 break; 1318 case Type.FLOAT: 1319 typ = Opcodes.T_FLOAT; 1320 break; 1321 case Type.LONG: 1322 typ = Opcodes.T_LONG; 1323 break; 1324 case Type.DOUBLE: 1325 typ = Opcodes.T_DOUBLE; 1326 break; 1327 default: 1328 typeInsn(Opcodes.ANEWARRAY, type); 1329 return; 1330 } 1331 mv.visitIntInsn(Opcodes.NEWARRAY, typ); 1332 } 1333 1334 1338 1341 public void arrayLength() { 1342 mv.visitInsn(Opcodes.ARRAYLENGTH); 1343 } 1344 1345 1348 public void throwException() { 1349 mv.visitInsn(Opcodes.ATHROW); 1350 } 1351 1352 1359 public void throwException(final Type type, final String msg) { 1360 newInstance(type); 1361 dup(); 1362 push(msg); 1363 invokeConstructor(type, Method.getMethod("void <init> (String)")); 1364 throwException(); 1365 } 1366 1367 1373 public void checkCast(final Type type) { 1374 if (!type.equals(OBJECT_TYPE)) { 1375 typeInsn(Opcodes.CHECKCAST, type); 1376 } 1377 } 1378 1379 1385 public void instanceOf(final Type type) { 1386 typeInsn(Opcodes.INSTANCEOF, type); 1387 } 1388 1389 1392 public void monitorEnter() { 1393 mv.visitInsn(Opcodes.MONITORENTER); 1394 } 1395 1396 1399 public void monitorExit() { 1400 mv.visitInsn(Opcodes.MONITOREXIT); 1401 } 1402 1403 1407 1410 public void endMethod() { 1411 if ((access & Opcodes.ACC_ABSTRACT) == 0) { 1412 mv.visitMaxs(0, 0); 1413 } 1414 } 1415 1416 1424 public void catchException( 1425 final Label start, 1426 final Label end, 1427 final Type exception) 1428 { 1429 mv.visitTryCatchBlock(start, end, mark(), exception.getInternalName()); 1430 } 1431} 1432 | Popular Tags |