1 /* 2 * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.reflect; 27 28 import java.lang.reflect.*; 29 import java.security.AccessController; 30 import java.security.PrivilegedAction; 31 import sun.misc.Unsafe; 32 33 /** Generator for sun.reflect.MethodAccessor and 34 sun.reflect.ConstructorAccessor objects using bytecodes to 35 implement reflection. A java.lang.reflect.Method or 36 java.lang.reflect.Constructor object can delegate its invoke or 37 newInstance method to an accessor using native code or to one 38 generated by this class. (Methods and Constructors were merged 39 together in this class to ensure maximum code sharing.) */ 40 41 class MethodAccessorGenerator extends AccessorGenerator { 42 43 private static final short NUM_BASE_CPOOL_ENTRIES = (short) 12; 44 // One for invoke() plus one for constructor 45 private static final short NUM_METHODS = (short) 2; 46 // Only used if forSerialization is true 47 private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2; 48 49 private static volatile int methodSymnum = 0; 50 private static volatile int constructorSymnum = 0; 51 private static volatile int serializationConstructorSymnum = 0; 52 53 private Class declaringClass; 54 private Class[] parameterTypes; 55 private Class returnType; 56 private boolean isConstructor; 57 private boolean forSerialization; 58 59 private short targetMethodRef; 60 private short invokeIdx; 61 private short invokeDescriptorIdx; 62 // Constant pool index of CONSTANT_Class_info for first 63 // non-primitive parameter type. Should be incremented by 2. 64 private short nonPrimitiveParametersBaseIdx; 65 66 MethodAccessorGenerator() { 67 } 68 69 /** This routine is not thread-safe */ 70 public MethodAccessor generateMethod(Class declaringClass, 71 String name, 72 Class[] parameterTypes, 73 Class returnType, 74 Class[] checkedExceptions, 75 int modifiers) 76 { 77 return (MethodAccessor) generate(declaringClass, 78 name, 79 parameterTypes, 80 returnType, 81 checkedExceptions, 82 modifiers, 83 false, 84 false, 85 null); 86 } 87 88 /** This routine is not thread-safe */ 89 public ConstructorAccessor generateConstructor(Class declaringClass, 90 Class[] parameterTypes, 91 Class[] checkedExceptions, 92 int modifiers) 93 { 94 return (ConstructorAccessor) generate(declaringClass, 95 "<init>", 96 parameterTypes, 97 Void.TYPE, 98 checkedExceptions, 99 modifiers, 100 true, 101 false, 102 null); 103 } 104 105 /** This routine is not thread-safe */ 106 public SerializationConstructorAccessorImpl 107 generateSerializationConstructor(Class declaringClass, 108 Class[] parameterTypes, 109 Class[] checkedExceptions, 110 int modifiers, 111 Class targetConstructorClass) 112 { 113 return (SerializationConstructorAccessorImpl) 114 generate(declaringClass, 115 "<init>", 116 parameterTypes, 117 Void.TYPE, 118 checkedExceptions, 119 modifiers, 120 true, 121 true, 122 targetConstructorClass); 123 } 124 125 /** This routine is not thread-safe */ 126 private MagicAccessorImpl generate(final Class declaringClass, 127 String name, 128 Class[] parameterTypes, 129 Class returnType, 130 Class[] checkedExceptions, 131 int modifiers, 132 boolean isConstructor, 133 boolean forSerialization, 134 Class serializationTargetClass) 135 { 136 ByteVector vec = ByteVectorFactory.create(); 137 asm = new ClassFileAssembler(vec); 138 this.declaringClass = declaringClass; 139 this.parameterTypes = parameterTypes; 140 this.returnType = returnType; 141 this.modifiers = modifiers; 142 this.isConstructor = isConstructor; 143 this.forSerialization = forSerialization; 144 145 asm.emitMagicAndVersion(); 146 147 // Constant pool entries: 148 // ( * = Boxing information: optional) 149 // (+ = Shared entries provided by AccessorGenerator) 150 // (^ = Only present if generating SerializationConstructorAccessor) 151 // [UTF-8] [This class's name] 152 // [CONSTANT_Class_info] for above 153 // [UTF-8] "sun/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}" 154 // [CONSTANT_Class_info] for above 155 // [UTF-8] [Target class's name] 156 // [CONSTANT_Class_info] for above 157 // ^ [UTF-8] [Serialization: Class's name in which to invoke constructor] 158 // ^ [CONSTANT_Class_info] for above 159 // [UTF-8] target method or constructor name 160 // [UTF-8] target method or constructor signature 161 // [CONSTANT_NameAndType_info] for above 162 // [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method 163 // [UTF-8] "invoke" or "newInstance" 164 // [UTF-8] invoke or newInstance descriptor 165 // [UTF-8] descriptor for type of non-primitive parameter 1 166 // [CONSTANT_Class_info] for type of non-primitive parameter 1 167 // ... 168 // [UTF-8] descriptor for type of non-primitive parameter n 169 // [CONSTANT_Class_info] for type of non-primitive parameter n 170 // + [UTF-8] "java/lang/Exception" 171 // + [CONSTANT_Class_info] for above 172 // + [UTF-8] "java/lang/ClassCastException" 173 // + [CONSTANT_Class_info] for above 174 // + [UTF-8] "java/lang/NullPointerException" 175 // + [CONSTANT_Class_info] for above 176 // + [UTF-8] "java/lang/IllegalArgumentException" 177 // + [CONSTANT_Class_info] for above 178 // + [UTF-8] "java/lang/InvocationTargetException" 179 // + [CONSTANT_Class_info] for above 180 // + [UTF-8] "<init>" 181 // + [UTF-8] "()V" 182 // + [CONSTANT_NameAndType_info] for above 183 // + [CONSTANT_Methodref_info] for NullPointerException's constructor 184 // + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor 185 // + [UTF-8] "(Ljava/lang/String;)V" 186 // + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V" 187 // + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String 188 // + [UTF-8] "(Ljava/lang/Throwable;)V" 189 // + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V" 190 // + [CONSTANT_Methodref_info] for InvocationTargetException's constructor 191 // + [CONSTANT_Methodref_info] for "super()" 192 // + [UTF-8] "java/lang/Object" 193 // + [CONSTANT_Class_info] for above 194 // + [UTF-8] "toString" 195 // + [UTF-8] "()Ljava/lang/String;" 196 // + [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;" 197 // + [CONSTANT_Methodref_info] for Object's toString method 198 // + [UTF-8] "Code" 199 // + [UTF-8] "Exceptions" 200 // * [UTF-8] "java/lang/Boolean" 201 // * [CONSTANT_Class_info] for above 202 // * [UTF-8] "(Z)V" 203 // * [CONSTANT_NameAndType_info] for above 204 // * [CONSTANT_Methodref_info] for above 205 // * [UTF-8] "booleanValue" 206 // * [UTF-8] "()Z" 207 // * [CONSTANT_NameAndType_info] for above 208 // * [CONSTANT_Methodref_info] for above 209 // * [UTF-8] "java/lang/Byte" 210 // * [CONSTANT_Class_info] for above 211 // * [UTF-8] "(B)V" 212 // * [CONSTANT_NameAndType_info] for above 213 // * [CONSTANT_Methodref_info] for above 214 // * [UTF-8] "byteValue" 215 // * [UTF-8] "()B" 216 // * [CONSTANT_NameAndType_info] for above 217 // * [CONSTANT_Methodref_info] for above 218 // * [UTF-8] "java/lang/Character" 219 // * [CONSTANT_Class_info] for above 220 // * [UTF-8] "(C)V" 221 // * [CONSTANT_NameAndType_info] for above 222 // * [CONSTANT_Methodref_info] for above 223 // * [UTF-8] "charValue" 224 // * [UTF-8] "()C" 225 // * [CONSTANT_NameAndType_info] for above 226 // * [CONSTANT_Methodref_info] for above 227 // * [UTF-8] "java/lang/Double" 228 // * [CONSTANT_Class_info] for above 229 // * [UTF-8] "(D)V" 230 // * [CONSTANT_NameAndType_info] for above 231 // * [CONSTANT_Methodref_info] for above 232 // * [UTF-8] "doubleValue" 233 // * [UTF-8] "()D" 234 // * [CONSTANT_NameAndType_info] for above 235 // * [CONSTANT_Methodref_info] for above 236 // * [UTF-8] "java/lang/Float" 237 // * [CONSTANT_Class_info] for above 238 // * [UTF-8] "(F)V" 239 // * [CONSTANT_NameAndType_info] for above 240 // * [CONSTANT_Methodref_info] for above 241 // * [UTF-8] "floatValue" 242 // * [UTF-8] "()F" 243 // * [CONSTANT_NameAndType_info] for above 244 // * [CONSTANT_Methodref_info] for above 245 // * [UTF-8] "java/lang/Integer" 246 // * [CONSTANT_Class_info] for above 247 // * [UTF-8] "(I)V" 248 // * [CONSTANT_NameAndType_info] for above 249 // * [CONSTANT_Methodref_info] for above 250 // * [UTF-8] "intValue" 251 // * [UTF-8] "()I" 252 // * [CONSTANT_NameAndType_info] for above 253 // * [CONSTANT_Methodref_info] for above 254 // * [UTF-8] "java/lang/Long" 255 // * [CONSTANT_Class_info] for above 256 // * [UTF-8] "(J)V" 257 // * [CONSTANT_NameAndType_info] for above 258 // * [CONSTANT_Methodref_info] for above 259 // * [UTF-8] "longValue" 260 // * [UTF-8] "()J" 261 // * [CONSTANT_NameAndType_info] for above 262 // * [CONSTANT_Methodref_info] for above 263 // * [UTF-8] "java/lang/Short" 264 // * [CONSTANT_Class_info] for above 265 // * [UTF-8] "(S)V" 266 // * [CONSTANT_NameAndType_info] for above 267 // * [CONSTANT_Methodref_info] for above 268 // * [UTF-8] "shortValue" 269 // * [UTF-8] "()S" 270 // * [CONSTANT_NameAndType_info] for above 271 // * [CONSTANT_Methodref_info] for above 272 273 short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES; 274 boolean usesPrimitives = usesPrimitiveTypes(); 275 if (usesPrimitives) { 276 numCPEntries += NUM_BOXING_CPOOL_ENTRIES; 277 } 278 if (forSerialization) { 279 numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES; 280 } 281 282 // Add in variable-length number of entries to be able to describe 283 // non-primitive parameter types and checked exceptions. 284 numCPEntries += (short) (2 * numNonPrimitiveParameterTypes()); 285 286 asm.emitShort(add(numCPEntries, S1)); 287 288 final String generatedName = generateName(isConstructor, forSerialization); 289 asm.emitConstantPoolUTF8(generatedName); 290 asm.emitConstantPoolClass(asm.cpi()); 291 thisClass = asm.cpi(); 292 if (isConstructor) { 293 if (forSerialization) { 294 asm.emitConstantPoolUTF8 295 ("sun/reflect/SerializationConstructorAccessorImpl"); 296 } else { 297 asm.emitConstantPoolUTF8("sun/reflect/ConstructorAccessorImpl"); 298 } 299 } else { 300 asm.emitConstantPoolUTF8("sun/reflect/MethodAccessorImpl"); 301 } 302 asm.emitConstantPoolClass(asm.cpi()); 303 superClass = asm.cpi(); 304 asm.emitConstantPoolUTF8(getClassName(declaringClass, false)); 305 asm.emitConstantPoolClass(asm.cpi()); 306 targetClass = asm.cpi(); 307 short serializationTargetClassIdx = (short) 0; 308 if (forSerialization) { 309 asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false)); 310 asm.emitConstantPoolClass(asm.cpi()); 311 serializationTargetClassIdx = asm.cpi(); 312 } 313 asm.emitConstantPoolUTF8(name); 314 asm.emitConstantPoolUTF8(buildInternalSignature()); 315 asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); 316 if (isInterface()) { 317 asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi()); 318 } else { 319 if (forSerialization) { 320 asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi()); 321 } else { 322 asm.emitConstantPoolMethodref(targetClass, asm.cpi()); 323 } 324 } 325 targetMethodRef = asm.cpi(); 326 if (isConstructor) { 327 asm.emitConstantPoolUTF8("newInstance"); 328 } else { 329 asm.emitConstantPoolUTF8("invoke"); 330 } 331 invokeIdx = asm.cpi(); 332 if (isConstructor) { 333 asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;"); 334 } else { 335 asm.emitConstantPoolUTF8 336 ("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); 337 } 338 invokeDescriptorIdx = asm.cpi(); 339 340 // Output class information for non-primitive parameter types 341 nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2); 342 for (int i = 0; i < parameterTypes.length; i++) { 343 Class c = parameterTypes[i]; 344 if (!isPrimitive(c)) { 345 asm.emitConstantPoolUTF8(getClassName(c, false)); 346 asm.emitConstantPoolClass(asm.cpi()); 347 } 348 } 349 350 // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor 351 emitCommonConstantPoolEntries(); 352 353 // Boxing entries 354 if (usesPrimitives) { 355 emitBoxingContantPoolEntries(); 356 } 357 358 if (asm.cpi() != numCPEntries) { 359 throw new InternalError("Adjust this code (cpi = " + asm.cpi() + 360 ", numCPEntries = " + numCPEntries + ")"); 361 } 362 363 // Access flags 364 asm.emitShort(ACC_PUBLIC); 365 366 // This class 367 asm.emitShort(thisClass); 368 369 // Superclass 370 asm.emitShort(superClass); 371 372 // Interfaces count and interfaces 373 asm.emitShort(S0); 374 375 // Fields count and fields 376 asm.emitShort(S0); 377 378 // Methods count and methods 379 asm.emitShort(NUM_METHODS); 380 381 emitConstructor(); 382 emitInvoke(); 383 384 // Additional attributes (none) 385 asm.emitShort(S0); 386 387 // Load class 388 vec.trim(); 389 final byte[] bytes = vec.getData(); 390 // Note: the class loader is the only thing that really matters 391 // here -- it's important to get the generated code into the 392 // same namespace as the target class. Since the generated code 393 // is privileged anyway, the protection domain probably doesn't 394 // matter. 395 return AccessController.doPrivileged( 396 new PrivilegedAction<MagicAccessorImpl>() { 397 public MagicAccessorImpl run() { 398 try { 399 return (MagicAccessorImpl) 400 ClassDefiner.defineClass 401 (generatedName, 402 bytes, 403 0, 404 bytes.length, 405 declaringClass.getClassLoader()).newInstance(); 406 } catch (InstantiationException e) { 407 throw (InternalError) 408 new InternalError().initCause(e); 409 } catch (IllegalAccessException e) { 410 throw (InternalError) 411 new InternalError().initCause(e); 412 } 413 } 414 }); 415 } 416 417 /** This emits the code for either invoke() or newInstance() */ 418 private void emitInvoke() { 419 // NOTE that this code will only handle 65535 parameters since we 420 // use the sipush instruction to get the array index on the 421 // operand stack. 422 if (parameterTypes.length > 65535) { 423 throw new InternalError("Can't handle more than 65535 parameters"); 424 } 425 426 // Generate code into fresh code buffer 427 ClassFileAssembler cb = new ClassFileAssembler(); 428 if (isConstructor) { 429 // 1 incoming argument 430 cb.setMaxLocals(2); 431 } else { 432 // 2 incoming arguments 433 cb.setMaxLocals(3); 434 } 435 436 short illegalArgStartPC = 0; 437 438 if (isConstructor) { 439 // Instantiate target class before continuing 440 // new <target class type> 441 // dup 442 cb.opc_new(targetClass); 443 cb.opc_dup(); 444 } else { 445 // Setup before iterating down argument list 446 if (isPrimitive(returnType)) { 447 // new <boxing type for primitive type> 448 // dup 449 // ... (see below:) 450 // invokespecial <constructor for boxing type for primitive type> 451 // areturn 452 cb.opc_new(indexForPrimitiveType(returnType)); 453 cb.opc_dup(); 454 } 455 456 // Get target object on operand stack if necessary. 457 458 // We need to do an explicit null check here; we won't see 459 // NullPointerExceptions from the invoke bytecode, since it's 460 // covered by an exception handler. 461 if (!isStatic()) { 462 // aload_1 463 // ifnonnull <checkcast label> 464 // new <NullPointerException> 465 // dup 466 // invokespecial <NullPointerException ctor> 467 // athrow 468 // <checkcast label:> 469 // aload_1 470 // checkcast <target class's type> 471 cb.opc_aload_1(); 472 Label l = new Label(); 473 cb.opc_ifnonnull(l); 474 cb.opc_new(nullPointerClass); 475 cb.opc_dup(); 476 cb.opc_invokespecial(nullPointerCtorIdx, 0, 0); 477 cb.opc_athrow(); 478 l.bind(); 479 illegalArgStartPC = cb.getLength(); 480 cb.opc_aload_1(); 481 cb.opc_checkcast(targetClass); 482 } 483 } 484 485 // Have to check length of incoming array and throw 486 // IllegalArgumentException if not correct. A concession to the 487 // JCK (isn't clearly specified in the spec): we allow null in the 488 // case where the argument list is zero length. 489 // if no-arg: 490 // aload_2 | aload_1 (Method | Constructor) 491 // ifnull <success label> 492 // aload_2 | aload_1 493 // arraylength 494 // sipush <num parameter types> 495 // if_icmpeq <success label> 496 // new <IllegalArgumentException> 497 // dup 498 // invokespecial <IllegalArgumentException ctor> 499 // athrow 500 // <success label:> 501 Label successLabel = new Label(); 502 if (parameterTypes.length == 0) { 503 if (isConstructor) { 504 cb.opc_aload_1(); 505 } else { 506 cb.opc_aload_2(); 507 } 508 cb.opc_ifnull(successLabel); 509 } 510 if (isConstructor) { 511 cb.opc_aload_1(); 512 } else { 513 cb.opc_aload_2(); 514 } 515 cb.opc_arraylength(); 516 cb.opc_sipush((short) parameterTypes.length); 517 cb.opc_if_icmpeq(successLabel); 518 cb.opc_new(illegalArgumentClass); 519 cb.opc_dup(); 520 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); 521 cb.opc_athrow(); 522 successLabel.bind(); 523 524 // Iterate through incoming actual parameters, ensuring that each 525 // is compatible with the formal parameter type, and pushing the 526 // actual on the operand stack (unboxing and widening if necessary). 527 528 short paramTypeCPIdx = nonPrimitiveParametersBaseIdx; 529 Label nextParamLabel = null; 530 byte count = 1; // both invokeinterface opcode's "count" as well as 531 // num args of other invoke bytecodes 532 for (int i = 0; i < parameterTypes.length; i++) { 533 Class paramType = parameterTypes[i]; 534 count += (byte) typeSizeInStackSlots(paramType); 535 if (nextParamLabel != null) { 536 nextParamLabel.bind(); 537 nextParamLabel = null; 538 } 539 // aload_2 | aload_1 540 // sipush <index> 541 // aaload 542 if (isConstructor) { 543 cb.opc_aload_1(); 544 } else { 545 cb.opc_aload_2(); 546 } 547 cb.opc_sipush((short) i); 548 cb.opc_aaload(); 549 if (isPrimitive(paramType)) { 550 // Unboxing code. 551 // Put parameter into temporary local variable 552 // astore_3 | astore_2 553 if (isConstructor) { 554 cb.opc_astore_2(); 555 } else { 556 cb.opc_astore_3(); 557 } 558 559 // repeat for all possible widening conversions: 560 // aload_3 | aload_2 561 // instanceof <primitive boxing type> 562 // ifeq <next unboxing label> 563 // aload_3 | aload_2 564 // checkcast <primitive boxing type> // Note: this is "redundant", 565 // // but necessary for the verifier 566 // invokevirtual <unboxing method> 567 // <widening conversion bytecode, if necessary> 568 // goto <next parameter label> 569 // <next unboxing label:> ... 570 // last unboxing label: 571 // new <IllegalArgumentException> 572 // dup 573 // invokespecial <IllegalArgumentException ctor> 574 // athrow 575 576 Label l = null; // unboxing label 577 nextParamLabel = new Label(); 578 579 for (int j = 0; j < primitiveTypes.length; j++) { 580 Class c = primitiveTypes[j]; 581 if (canWidenTo(c, paramType)) { 582 if (l != null) { 583 l.bind(); 584 } 585 // Emit checking and unboxing code for this type 586 if (isConstructor) { 587 cb.opc_aload_2(); 588 } else { 589 cb.opc_aload_3(); 590 } 591 cb.opc_instanceof(indexForPrimitiveType(c)); 592 l = new Label(); 593 cb.opc_ifeq(l); 594 if (isConstructor) { 595 cb.opc_aload_2(); 596 } else { 597 cb.opc_aload_3(); 598 } 599 cb.opc_checkcast(indexForPrimitiveType(c)); 600 cb.opc_invokevirtual(unboxingMethodForPrimitiveType(c), 601 0, 602 typeSizeInStackSlots(c)); 603 emitWideningBytecodeForPrimitiveConversion(cb, 604 c, 605 paramType); 606 cb.opc_goto(nextParamLabel); 607 } 608 } 609 610 if (l == null) { 611 throw new InternalError 612 ("Must have found at least identity conversion"); 613 } 614 615 // Fell through; given object is null or invalid. According to 616 // the spec, we can throw IllegalArgumentException for both of 617 // these cases. 618 619 l.bind(); 620 cb.opc_new(illegalArgumentClass); 621 cb.opc_dup(); 622 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); 623 cb.opc_athrow(); 624 } else { 625 // Emit appropriate checkcast 626 cb.opc_checkcast(paramTypeCPIdx); 627 paramTypeCPIdx = add(paramTypeCPIdx, S2); 628 // Fall through to next argument 629 } 630 } 631 // Bind last goto if present 632 if (nextParamLabel != null) { 633 nextParamLabel.bind(); 634 } 635 636 short invokeStartPC = cb.getLength(); 637 638 // OK, ready to perform the invocation. 639 if (isConstructor) { 640 cb.opc_invokespecial(targetMethodRef, count, 0); 641 } else { 642 if (isStatic()) { 643 cb.opc_invokestatic(targetMethodRef, 644 count, 645 typeSizeInStackSlots(returnType)); 646 } else { 647 if (isInterface()) { 648 cb.opc_invokeinterface(targetMethodRef, 649 count, 650 count, 651 typeSizeInStackSlots(returnType)); 652 } else { 653 cb.opc_invokevirtual(targetMethodRef, 654 count, 655 typeSizeInStackSlots(returnType)); 656 } 657 } 658 } 659 660 short invokeEndPC = cb.getLength(); 661 662 if (!isConstructor) { 663 // Box return value if necessary 664 if (isPrimitive(returnType)) { 665 cb.opc_invokespecial(ctorIndexForPrimitiveType(returnType), 666 typeSizeInStackSlots(returnType), 667 0); 668 } else if (returnType == Void.TYPE) { 669 cb.opc_aconst_null(); 670 } 671 } 672 cb.opc_areturn(); 673 674 // We generate two exception handlers; one which is responsible 675 // for catching ClassCastException and NullPointerException and 676 // throwing IllegalArgumentException, and the other which catches 677 // all java/lang/Throwable objects thrown from the target method 678 // and wraps them in InvocationTargetExceptions. 679 680 short classCastHandler = cb.getLength(); 681 682 // ClassCast, etc. exception handler 683 cb.setStack(1); 684 cb.opc_invokespecial(toStringIdx, 0, 1); 685 cb.opc_new(illegalArgumentClass); 686 cb.opc_dup_x1(); 687 cb.opc_swap(); 688 cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0); 689 cb.opc_athrow(); 690 691 short invocationTargetHandler = cb.getLength(); 692 693 // InvocationTargetException exception handler 694 cb.setStack(1); 695 cb.opc_new(invocationTargetClass); 696 cb.opc_dup_x1(); 697 cb.opc_swap(); 698 cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0); 699 cb.opc_athrow(); 700 701 // Generate exception table. We cover the entire code sequence 702 // with an exception handler which catches ClassCastException and 703 // converts it into an IllegalArgumentException. 704 705 ClassFileAssembler exc = new ClassFileAssembler(); 706 707 exc.emitShort(illegalArgStartPC); // start PC 708 exc.emitShort(invokeStartPC); // end PC 709 exc.emitShort(classCastHandler); // handler PC 710 exc.emitShort(classCastClass); // catch type 711 712 exc.emitShort(illegalArgStartPC); // start PC 713 exc.emitShort(invokeStartPC); // end PC 714 exc.emitShort(classCastHandler); // handler PC 715 exc.emitShort(nullPointerClass); // catch type 716 717 exc.emitShort(invokeStartPC); // start PC 718 exc.emitShort(invokeEndPC); // end PC 719 exc.emitShort(invocationTargetHandler); // handler PC 720 exc.emitShort(throwableClass); // catch type 721 722 emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc, 723 new short[] { invocationTargetClass }); 724 } 725 726 private boolean usesPrimitiveTypes() { 727 // We need to emit boxing/unboxing constant pool information if 728 // the method takes a primitive type for any of its parameters or 729 // returns a primitive value (except void) 730 if (returnType.isPrimitive()) { 731 return true; 732 } 733 for (int i = 0; i < parameterTypes.length; i++) { 734 if (parameterTypes[i].isPrimitive()) { 735 return true; 736 } 737 } 738 return false; 739 } 740 741 private int numNonPrimitiveParameterTypes() { 742 int num = 0; 743 for (int i = 0; i < parameterTypes.length; i++) { 744 if (!parameterTypes[i].isPrimitive()) { 745 ++num; 746 } 747 } 748 return num; 749 } 750 751 private boolean isInterface() { 752 return declaringClass.isInterface(); 753 } 754 755 private String buildInternalSignature() { 756 StringBuffer buf = new StringBuffer(); 757 buf.append("("); 758 for (int i = 0; i < parameterTypes.length; i++) { 759 buf.append(getClassName(parameterTypes[i], true)); 760 } 761 buf.append(")"); 762 buf.append(getClassName(returnType, true)); 763 return buf.toString(); 764 } 765 766 private static synchronized String generateName(boolean isConstructor, 767 boolean forSerialization) 768 { 769 if (isConstructor) { 770 if (forSerialization) { 771 int num = ++serializationConstructorSymnum; 772 return "sun/reflect/GeneratedSerializationConstructorAccessor" + num; 773 } else { 774 int num = ++constructorSymnum; 775 return "sun/reflect/GeneratedConstructorAccessor" + num; 776 } 777 } else { 778 int num = ++methodSymnum; 779 return "sun/reflect/GeneratedMethodAccessor" + num; 780 } 781 } 782 }