1 32 package org.objectweb.proactive.core.mop; 33 34 import java.lang.reflect.Method ; 35 import java.lang.reflect.Modifier ; 36 import java.util.Vector ; 37 38 import org.apache.log4j.Logger; 39 import org.objectweb.asm.ClassWriter; 40 import org.objectweb.asm.CodeVisitor; 41 import org.objectweb.asm.Constants; 42 import org.objectweb.asm.Label; 43 import org.objectweb.asm.Type; 44 45 public class ASMBytecodeStubBuilder implements Constants { 46 47 protected static Logger logger = Logger.getLogger(ASMBytecodeStubBuilder.class.getName()); 48 49 protected Class cl; 52 protected String className; 53 protected String packageName; 54 protected Method [] methods; 55 56 protected String stubClassSimpleName; 59 protected String stubClassFullName; 60 protected ClassWriter classGenerator; 61 62 protected static final String METHODCALL_TYPE = "Lorg/objectweb/proactive/core/mop/MethodCall;"; 64 protected static final String OBJECT_TYPE = "Ljava/lang/Object;"; 65 protected static final String OBJECT_ARRAY_TYPE = "[Ljava/lang/Object;"; 66 protected static final String METHOD_TYPE = "Ljava/lang/reflect/Method;"; 67 protected static final String METHOD_ARRAY_TYPE = "[Ljava/lang/reflect/Method;"; 68 protected static final String PROXY_TYPE = "Lorg/objectweb/proactive/core/mop/Proxy;"; 69 protected static final String STUB_INTERFACE_NAME = "org/objectweb/proactive/core/mop/StubObject"; 70 protected static final String PROXY_FIELD_NAME = "myProxy"; 71 72 public ASMBytecodeStubBuilder(String classname) throws ClassNotFoundException { 73 logger.debug("ASMBytecodeStubBuilder.init<> classname " + classname); 77 try { 78 this.cl = Class.forName(classname); 79 } catch (ClassNotFoundException e) { 80 e.printStackTrace(); 81 throw e; 82 } 83 logger.debug("ASMBytecodeStubBuilder.init<> 1"); 84 this.className = classname; 86 logger.debug("ASMBytecodeStubBuilder.init<> 2"); 87 this.setInfos(); 89 } 90 110 protected ClassWriter createClassGenerator() { 111 String superclassName; 112 String [] interfaces; 113 114 if (this.cl.isInterface()) { 118 superclassName = "java.lang.Object"; 119 interfaces = new String [3]; 120 interfaces[0] = "java/io/Serializable"; 121 interfaces[1] = STUB_INTERFACE_NAME; 122 interfaces[2] = this.cl.getName().replace('.', '/'); 123 } else { 124 superclassName = this.className; 125 interfaces = new String [2]; 126 interfaces[0] = "java/io/Serializable"; 127 interfaces[1] = STUB_INTERFACE_NAME; 128 } 129 130 ClassWriter cw = new ClassWriter(true); 131 cw.visit(Constants.ACC_PUBLIC | Constants.ACC_SUPER, this.stubClassFullName.replace('.', '/'), superclassName.replace('.', '/'), interfaces, "<generated>"); 136 return cw; 137 } 138 139 public byte[] create() { 140 this.classGenerator = this.createClassGenerator(); 142 143 this.createConstructor(); 145 146 for (int i = 0; i < this.methods.length; i++) { 148 CodeVisitor mg = this.createMethod(i, this.methods[i]); 149 } 150 151 this.createGetAndSetProxyMethods(); 154 155 this.createFields(); 157 158 this.createStaticVariables(); 160 161 this.createStaticInitializer(); 163 164 175 return this.classGenerator.toByteArray(); 176 } 177 178 protected CodeVisitor createMethodGenerator(Method m) { 179 int flags = convertJavaModifierToASM(m.getModifiers()); 181 182 flags = removeNativeAndAbstractModifiers(flags); 184 185 String mDesc = Type.getMethodDescriptor(m); 187 188 CodeVisitor cv = this.classGenerator.visitMethod(flags, m.getName(), mDesc, null, null); return cv; 195 } 196 197 protected static int removeNativeAndAbstractModifiers(int modifiers) { 198 int result = modifiers & (~Modifier.NATIVE); 202 result = result & (~Modifier.ABSTRACT); 203 return result; 204 } 205 206 protected static int convertJavaModifierToASM(int javaModifier) { 207 int result = 0; 208 209 if (Modifier.isAbstract(javaModifier)) { 210 result = result | Constants.ACC_ABSTRACT; 211 } 212 if (Modifier.isFinal(javaModifier)) { 213 result = result | Constants.ACC_FINAL; 214 } 215 if (Modifier.isInterface(javaModifier)) { 216 result = result | Constants.ACC_INTERFACE; 217 } 218 if (Modifier.isNative(javaModifier)) { 219 result = result | Constants.ACC_NATIVE; 220 } 221 if (Modifier.isPrivate(javaModifier)) { 222 result = result | Constants.ACC_PRIVATE; 223 } 224 if (Modifier.isProtected(javaModifier)) { 225 result = result | Constants.ACC_PROTECTED; 226 } 227 if (Modifier.isPublic(javaModifier)) { 228 result = result | Constants.ACC_PUBLIC; 229 } 230 if (Modifier.isStatic(javaModifier)) { 231 result = result | Constants.ACC_STATIC; 232 } 233 if (Modifier.isSynchronized(javaModifier)) { 234 result = result | Constants.ACC_SYNCHRONIZED; 235 } 236 if (Modifier.isTransient(javaModifier)) { 237 result = result | Constants.ACC_TRANSIENT; 238 } 239 if (Modifier.isVolatile(javaModifier)) { 240 result = result | Constants.ACC_VOLATILE; 241 } 242 243 return result; 244 } 245 246 protected CodeVisitor createMethod(int methodIndex, Method m) { 247 CodeVisitor cv = createMethodGenerator(m); 248 Label inConstructorHandle = new Label(); 250 251 if (this.cl.isInterface() == false) { 252 cv.visitVarInsn(ALOAD, 0); 255 256 cv.visitFieldInsn(GETFIELD, this.stubClassFullName.replace('.', '/'), "outsideConstructor", "Z"); 258 259 cv.visitJumpInsn(IFEQ, inConstructorHandle); 263 } 264 265 268 cv.visitVarInsn(ALOAD, 0); 270 cv.visitFieldInsn(GETFIELD, this.stubClassFullName.replace('.', '/'), PROXY_FIELD_NAME, PROXY_TYPE); 271 272 cv.visitFieldInsn(GETSTATIC, this.stubClassFullName.replace('.', '/'), "methods", METHOD_ARRAY_TYPE); 274 pushInt(cv, methodIndex); 275 cv.visitInsn(AALOAD); 276 277 Class [] paramTypes = m.getParameterTypes(); 278 pushInt(cv, paramTypes.length); 281 cv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); 283 284 int indexInParameterArray = 1; for (int i = 0; i < paramTypes.length; i++) { 287 cv.visitInsn(DUP); 290 291 pushInt(cv, i); 293 294 Class param = paramTypes[i]; 296 297 if (param.isPrimitive()) { 299 int opcode = ILOAD; 300 String type; 301 String desc; 302 if (param == Byte.TYPE) { 303 type = "java/lang/Byte"; 304 desc = "B"; 305 } else if (param == Integer.TYPE) { 306 type = "java/lang/Integer"; 307 desc = "I"; 308 } else if (param == Boolean.TYPE) { 309 type = "java/lang/Boolean"; 310 desc = "Z"; 311 } else if (param == Double.TYPE) { 312 opcode = DLOAD; 313 type = "java/lang/Double"; 314 desc = "D"; 315 } else if (param == Float.TYPE) { 316 opcode = FLOAD; 317 type = "java/lang/Float"; 318 desc = "F"; 319 } else if (param == Long.TYPE) { 320 opcode = LLOAD; 321 type = "java/lang/Long"; 322 desc = "J"; 323 } else if (param == Character.TYPE) { 324 type = "java/lang/Character"; 325 desc = "C"; 326 } else { 327 type = "java/lang/Short"; 328 desc = "S"; 329 } 330 cv.visitTypeInsn(NEW, type); 331 cv.visitInsn(DUP); 332 cv.visitVarInsn(opcode, indexInParameterArray); 333 cv.visitMethodInsn(INVOKESPECIAL, type, "<init>", "(" + desc + ")V"); 334 } else { 335 cv.visitVarInsn(ALOAD, indexInParameterArray); 336 } 337 indexInParameterArray += (param == Double.TYPE || param == Long.TYPE ? 2 : 1); 338 339 cv.visitInsn(AASTORE); 341 } 342 343 cv.visitMethodInsn( 346 INVOKESTATIC, 347 "org/objectweb/proactive/core/mop/MethodCall", 348 "getMethodCall", 349 "(" + METHOD_TYPE + OBJECT_ARRAY_TYPE + ")" + METHODCALL_TYPE); 350 351 cv.visitMethodInsn( 353 INVOKEINTERFACE, 356 "org/objectweb/proactive/core/mop/Proxy", 357 "reify", 358 "(" + METHODCALL_TYPE + ")" + OBJECT_TYPE); 359 360 if (m.getReturnType().isPrimitive()) { 363 this.createUnwrappingCode(cv, m.getReturnType()); 364 } else { 365 cv.visitTypeInsn(CHECKCAST, Type.getInternalName(m.getReturnType())); 368 } 369 370 if (this.cl.isInterface() == false) { 374 Label returnHandle = new Label(); 378 cv.visitJumpInsn(GOTO, returnHandle); 379 380 cv.visitLabel(inConstructorHandle); 383 cv.visitVarInsn(ALOAD, 0); 384 385 386 indexInParameterArray = 1; 389 for (int i = 0; i < paramTypes.length; ++i) { 390 cv.visitVarInsn(ILOAD + getOpcodeOffset(paramTypes[i]), indexInParameterArray); 391 indexInParameterArray += getSize(paramTypes[i]); 392 } 393 394 String declaringClassName = this.methods[methodIndex].getDeclaringClass().getName(); 396 cv.visitMethodInsn( 397 INVOKESPECIAL, 398 declaringClassName.replace('.', '/'), 399 m.getName(), 400 Type.getMethodDescriptor(m)); 401 402 cv.visitLabel(returnHandle); 404 createReturnCode(cv, m.getReturnType()); 405 406 } else { 407 createReturnCode(cv, m.getReturnType()); 411 } 412 cv.visitMaxs(0, 0); 414 return cv; 415 } 416 417 protected void createUnwrappingCode(CodeVisitor cv, Class c) { 418 422 if (c == Void.TYPE) { 423 cv.visitInsn(POP); 424 } else if (c.isPrimitive()) { 425 String type; 426 String meth; 427 String desc; 428 if (c == Byte.TYPE) { 429 type = "java/lang/Byte"; 430 meth = "byteValue"; 431 desc = "B"; 432 } else if (c == Integer.TYPE) { 433 type = "java/lang/Integer"; 434 meth = "intValue"; 435 desc = "I"; 436 } else if (c == Boolean.TYPE) { 437 type = "java/lang/Boolean"; 438 meth = "booleanValue"; 439 desc = "Z"; 440 } else if (c == Double.TYPE) { 441 type = "java/lang/Double"; 442 meth = "doubleValue"; 443 desc = "D"; 444 } else if (c == Float.TYPE) { 445 type = "java/lang/Float"; 446 meth = "floatValue"; 447 desc = "F"; 448 } else if (c == Long.TYPE) { 449 type = "java/lang/Long"; 450 meth = "longValue"; 451 desc = "J"; 452 } else if (c == Character.TYPE) { 453 type = "java/lang/Character"; 454 meth = "charValue"; 455 desc = "C"; 456 } else { 457 type = "java/lang/Short"; 458 meth = "shortValue"; 459 desc = "S"; 460 } 461 cv.visitTypeInsn(CHECKCAST, type); 462 cv.visitMethodInsn(INVOKEVIRTUAL, type, meth, "()" + desc); 463 } else { 464 cv.visitTypeInsn(CHECKCAST, Type.getInternalName(c)); 465 } 466 467 return; 468 } 469 470 protected void createReturnCode(CodeVisitor cv, Class c) { 471 if (c == Void.TYPE) { 472 cv.visitInsn(RETURN); 473 } else if (c.isPrimitive()) { 474 int opcode; 475 if (c == Double.TYPE) { 476 opcode = DRETURN; 477 } else if (c == Float.TYPE) { 478 opcode = FRETURN; 479 } else if (c == Long.TYPE) { 480 opcode = LRETURN; 481 } else { 482 opcode = IRETURN; 483 } 484 cv.visitInsn(opcode); 485 } else { 486 cv.visitInsn(ARETURN); 487 } 488 } 489 490 protected void createFields() { 491 if (!this.cl.isInterface()) { 496 this.classGenerator.visitField(ACC_PROTECTED, "outsideConstructor", "Z", null, null); 497 } 498 this.classGenerator.visitField(ACC_PROTECTED, PROXY_FIELD_NAME, PROXY_TYPE, null, null); 500 } 501 502 protected void createConstructor() { 503 CodeVisitor cv = this.classGenerator.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 505 506 if (!this.cl.isInterface()) { 507 cv.visitVarInsn(ALOAD, 0); 509 cv.visitMethodInsn(INVOKESPECIAL, this.className.replace('.', '/'), "<init>", "()V"); 510 511 cv.visitVarInsn(ALOAD, 0); 513 cv.visitInsn(ICONST_1); 514 cv.visitFieldInsn(PUTFIELD, this.stubClassFullName.replace('.', '/'), "outsideConstructor", "Z"); 515 } else { 516 cv.visitVarInsn(ALOAD, 0); 518 cv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); 519 } 520 521 cv.visitInsn(RETURN); 523 524 cv.visitMaxs(0, 0); 527 528 529 return; 530 } 531 532 protected void createStaticVariables() { 533 this.classGenerator.visitField(ACC_PROTECTED | ACC_STATIC, "methods", METHOD_ARRAY_TYPE, null, null); 536 return; 537 } 538 539 protected void createStaticInitializer() { 540 CodeVisitor cv = this.classGenerator.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); 542 543 pushInt(cv, this.methods.length); 547 cv.visitTypeInsn(ANEWARRAY, "java/lang/reflect/Method"); 549 550 cv.visitFieldInsn(PUTSTATIC, this.stubClassFullName.replace('.', '/'), "methods", METHOD_ARRAY_TYPE); 552 553 Vector vectorOfSuperClasses = new Vector (); 556 Class currentClass = cl; 557 while (currentClass != null) { 558 vectorOfSuperClasses.addElement(currentClass); 559 currentClass = currentClass.getSuperclass(); 560 } 561 562 pushInt(cv, vectorOfSuperClasses.size()); 564 cv.visitTypeInsn(ANEWARRAY, "java/lang/Class"); 566 cv.visitVarInsn(ASTORE, 1); 568 569 for (int i = 0; i < vectorOfSuperClasses.size(); i++) { 571 cv.visitVarInsn(ALOAD, 1); 573 pushInt(cv, i); 575 String s = ((Class ) vectorOfSuperClasses.elementAt(i)).getName(); 577 cv.visitLdcInsn(s); 578 cv.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;"); 580 581 cv.visitInsn(AASTORE); 585 } 586 587 for (int i = 0; i < this.methods.length; i++) { 589 cv.visitFieldInsn(GETSTATIC, this.stubClassFullName.replace('.', '/'), "methods", METHOD_ARRAY_TYPE); 591 pushInt(cv, i); 592 593 int indexInClassArray = vectorOfSuperClasses.indexOf(this.methods[i].getDeclaringClass()); 595 if (indexInClassArray == -1) { 596 } 597 cv.visitVarInsn(ALOAD, 1); 599 pushInt(cv, indexInClassArray); 601 cv.visitInsn(AALOAD); 602 cv.visitLdcInsn(this.methods[i].getName()); 605 pushInt(cv, this.methods[i].getParameterTypes().length); 610 cv.visitTypeInsn(ANEWARRAY, "java/lang/Class"); 612 cv.visitVarInsn(ASTORE, 2); 614 615 for (int j = 0; j < this.methods[i].getParameterTypes().length; j++) { 617 Class currentParameter = this.methods[i].getParameterTypes()[j]; 618 619 cv.visitVarInsn(ALOAD, 2); 621 pushInt(cv, j); 623 624 if (currentParameter.isPrimitive()) { 627 cv.visitFieldInsn( 629 GETSTATIC, 630 Type.getInternalName(Utils.getWrapperClass(currentParameter)), 631 "TYPE", 632 "Ljava/lang/Class;"); 633 } else { 634 cv.visitLdcInsn(currentParameter.getName()); 636 cv.visitMethodInsn( 638 INVOKESTATIC, 639 "java/lang/Class", 640 "forName", 641 "(Ljava/lang/String;)Ljava/lang/Class;"); 642 } 643 644 cv.visitInsn(AASTORE); 646 } 647 648 cv.visitVarInsn(ALOAD, 2); 650 651 cv.visitMethodInsn( 653 INVOKEVIRTUAL, 654 "java/lang/Class", 655 "getDeclaredMethod", 656 "(Ljava/lang/String;[Ljava/lang/Class;)" + METHOD_TYPE); 657 cv.visitInsn(AASTORE); 659 } 660 661 cv.visitInsn(RETURN); 663 664 cv.visitMaxs(0, 0); 667 668 return; 669 } 670 671 protected void createGetAndSetProxyMethods() { 672 CodeVisitor cv = this.classGenerator.visitMethod(ACC_PUBLIC, "getProxy", "()" + PROXY_TYPE, null, null); 674 675 cv.visitVarInsn(ALOAD, 0); 677 cv.visitFieldInsn(GETFIELD, this.stubClassFullName.replace('.', '/'), PROXY_FIELD_NAME, PROXY_TYPE); 678 cv.visitInsn(ARETURN); 679 680 cv.visitMaxs(0, 0); 683 684 cv = this.classGenerator.visitMethod(ACC_PUBLIC, "setProxy", "(" + PROXY_TYPE + ")V", null, null); 686 687 cv.visitVarInsn(ALOAD, 0); 689 cv.visitVarInsn(ALOAD, 1); 690 cv.visitFieldInsn(PUTFIELD, this.stubClassFullName.replace('.', '/'), PROXY_FIELD_NAME, PROXY_TYPE); 691 cv.visitInsn(RETURN); 692 693 cv.visitMaxs(0, 0); 696 697 return; 698 } 699 700 701 protected static int lengthOfType(Class cl) { 702 int result; 703 if (cl.isPrimitive()) { 704 if ((cl.equals(Long.TYPE)) || (cl.equals(Double.TYPE))) { 705 result = 2; 706 } else { 707 result = 1; 708 } 709 } else { 710 result = 1; 711 } 712 return result; 713 } 714 715 718 719 protected void setInfos() { 720 logger.debug("ASMByteCodeStubBuilder.setInfos()"); 721 java.util.Hashtable temp = new java.util.Hashtable (); 724 725 Class currentClass = this.cl; 729 730 Vector tempVector = new Vector (); 732 Class [] params; 733 Object exists; 734 735 logger.debug("ASMByteCodeStubBuilder.setInfos() 1"); 738 if (this.cl.isInterface()) { 739 Method [] allPublicMethods = this.cl.getMethods(); 740 for (int i = 0; i < allPublicMethods.length; i++) { 741 tempVector.addElement(allPublicMethods[i]); 742 } 743 } else { 745 do { 747 logger.debug("ASMByteCodeStubBuilder.setInfos() 2"); 749 Method [] declaredMethods = currentClass.getDeclaredMethods(); 750 751 for (int i = 0; i < declaredMethods.length; i++) { 753 Method currentMethod = declaredMethods[i]; 754 String key = ""; 757 key = key + currentMethod.getName(); 758 params = currentMethod.getParameterTypes(); 759 for (int k = 0; k < params.length; k++) { 760 key = key + params[k].getName(); 761 } 762 logger.debug("ASMByteCodeStubBuilder.setInfos() 3"); 763 exists = temp.get(key); 765 if (exists == null) { 766 if ((key.equals("finalize")) && (params.length == 0)) { 770 } else { 772 tempVector.addElement(currentMethod); 775 temp.put(key, currentMethod); 776 } 777 } else { 778 } 781 } 782 currentClass = currentClass.getSuperclass(); 783 } while (currentClass != null); } 785 786 this.methods = new Method [tempVector.size()]; 788 tempVector.copyInto(this.methods); 789 790 794 Vector v = new Vector (); 795 int initialNumberOfMethods = this.methods.length; 796 797 for (int i = 0; i < initialNumberOfMethods; i++) { 798 if (Utils.checkMethod(this.methods[i])) { 799 v.addElement(this.methods[i]); 800 } 801 } 802 Method [] validMethods = new Method [v.size()]; 803 v.copyInto(validMethods); 804 805 this.methods = validMethods; 807 808 this.packageName = Utils.getPackageName(this.className); 809 this.stubClassFullName = Utils.convertClassNameToStubClassName(this.className); 810 this.stubClassSimpleName = Utils.getSimpleName(this.stubClassFullName); 811 812 return; 813 } 814 815 public String getStubClassFullName() { 816 return this.stubClassFullName; 817 } 818 819 821 static void pushInt(CodeVisitor cv, int i) { 822 if (i >= -128 && i < 128) { 823 cv.visitIntInsn(BIPUSH, i); 824 } else if (i >= -32768 && i < 32768) { 825 cv.visitIntInsn(SIPUSH, i); 826 } else { 827 cv.visitLdcInsn(new Integer (i)); 828 } 829 } 830 831 842 843 protected int getOpcodeOffset(final Class type) { 844 if (type == Double.TYPE) { 845 return 3; 846 } else if (type == Float.TYPE) { 847 return 2; 848 } else if (type == Long.TYPE) { 849 return 1; 850 } else if (type.isPrimitive()) { 851 return 0; 852 } 853 return 4; 854 } 855 856 863 864 protected int getSize(final Class type) { 865 return (type == Double.TYPE || type == Long.TYPE ? 2 : 1); 866 } 867 } 868 | Popular Tags |