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