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 26 package jdk.internal.reflect; 27 28 import java.security.AccessController; 29 import 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 39 class 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 public MagicAccessorImpl run() { 396 try { 397 return (MagicAccessorImpl) 398 ClassDefiner.defineClass 399 (generatedName, 400 bytes, 401 0, 402 bytes.length, 403 declaringClass.getClassLoader()).newInstance(); 404 } catch (InstantiationException | IllegalAccessException e) { 405 throw new InternalError(e); 406 } 407 } 408 }); 409 } 410 411 /** This emits the code for either invoke() or newInstance() */ 412 private void emitInvoke() { 413 // NOTE that this code will only handle 65535 parameters since we 414 // use the sipush instruction to get the array index on the 415 // operand stack. 416 if (parameterTypes.length > 65535) { 417 throw new InternalError("Can't handle more than 65535 parameters"); 418 } 419 420 // Generate code into fresh code buffer 421 ClassFileAssembler cb = new ClassFileAssembler(); 422 if (isConstructor) { 423 // 1 incoming argument 424 cb.setMaxLocals(2); 425 } else { 426 // 2 incoming arguments 427 cb.setMaxLocals(3); 428 } 429 430 short illegalArgStartPC = 0; 431 432 if (isConstructor) { 433 // Instantiate target class before continuing 434 // new <target class type> 435 // dup 436 cb.opc_new(targetClass); 437 cb.opc_dup(); 438 } else { 439 // Setup before iterating down argument list 440 if (isPrimitive(returnType)) { 441 // new <boxing type for primitive type> 442 // dup 443 // ... (see below:) 444 // invokespecial <constructor for boxing type for primitive type> 445 // areturn 446 cb.opc_new(indexForPrimitiveType(returnType)); 447 cb.opc_dup(); 448 } 449 450 // Get target object on operand stack if necessary. 451 452 // We need to do an explicit null check here; we won't see 453 // NullPointerExceptions from the invoke bytecode, since it's 454 // covered by an exception handler. 455 if (!isStatic()) { 456 // aload_1 457 // ifnonnull <checkcast label> 458 // new <NullPointerException> 459 // dup 460 // invokespecial <NullPointerException ctor> 461 // athrow 462 // <checkcast label:> 463 // aload_1 464 // checkcast <target class's type> 465 cb.opc_aload_1(); 466 Label l = new Label(); 467 cb.opc_ifnonnull(l); 468 cb.opc_new(nullPointerClass); 469 cb.opc_dup(); 470 cb.opc_invokespecial(nullPointerCtorIdx, 0, 0); 471 cb.opc_athrow(); 472 l.bind(); 473 illegalArgStartPC = cb.getLength(); 474 cb.opc_aload_1(); 475 cb.opc_checkcast(targetClass); 476 } 477 } 478 479 // Have to check length of incoming array and throw 480 // IllegalArgumentException if not correct. A concession to the 481 // JCK (isn't clearly specified in the spec): we allow null in the 482 // case where the argument list is zero length. 483 // if no-arg: 484 // aload_2 | aload_1 (Method | Constructor) 485 // ifnull <success label> 486 // aload_2 | aload_1 487 // arraylength 488 // sipush <num parameter types> 489 // if_icmpeq <success label> 490 // new <IllegalArgumentException> 491 // dup 492 // invokespecial <IllegalArgumentException ctor> 493 // athrow 494 // <success label:> 495 Label successLabel = new Label(); 496 if (parameterTypes.length == 0) { 497 if (isConstructor) { 498 cb.opc_aload_1(); 499 } else { 500 cb.opc_aload_2(); 501 } 502 cb.opc_ifnull(successLabel); 503 } 504 if (isConstructor) { 505 cb.opc_aload_1(); 506 } else { 507 cb.opc_aload_2(); 508 } 509 cb.opc_arraylength(); 510 cb.opc_sipush((short) parameterTypes.length); 511 cb.opc_if_icmpeq(successLabel); 512 cb.opc_new(illegalArgumentClass); 513 cb.opc_dup(); 514 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); 515 cb.opc_athrow(); 516 successLabel.bind(); 517 518 // Iterate through incoming actual parameters, ensuring that each 519 // is compatible with the formal parameter type, and pushing the 520 // actual on the operand stack (unboxing and widening if necessary). 521 522 short paramTypeCPIdx = nonPrimitiveParametersBaseIdx; 523 Label nextParamLabel = null; 524 byte count = 1; // both invokeinterface opcode's "count" as well as 525 // num args of other invoke bytecodes 526 for (int i = 0; i < parameterTypes.length; i++) { 527 Class<?> paramType = parameterTypes[i]; 528 count += (byte) typeSizeInStackSlots(paramType); 529 if (nextParamLabel != null) { 530 nextParamLabel.bind(); 531 nextParamLabel = null; 532 } 533 // aload_2 | aload_1 534 // sipush <index> 535 // aaload 536 if (isConstructor) { 537 cb.opc_aload_1(); 538 } else { 539 cb.opc_aload_2(); 540 } 541 cb.opc_sipush((short) i); 542 cb.opc_aaload(); 543 if (isPrimitive(paramType)) { 544 // Unboxing code. 545 // Put parameter into temporary local variable 546 // astore_3 | astore_2 547 if (isConstructor) { 548 cb.opc_astore_2(); 549 } else { 550 cb.opc_astore_3(); 551 } 552 553 // repeat for all possible widening conversions: 554 // aload_3 | aload_2 555 // instanceof <primitive boxing type> 556 // ifeq <next unboxing label> 557 // aload_3 | aload_2 558 // checkcast <primitive boxing type> // Note: this is "redundant", 559 // // but necessary for the verifier 560 // invokevirtual <unboxing method> 561 // <widening conversion bytecode, if necessary> 562 // goto <next parameter label> 563 // <next unboxing label:> ... 564 // last unboxing label: 565 // new <IllegalArgumentException> 566 // dup 567 // invokespecial <IllegalArgumentException ctor> 568 // athrow 569 570 Label l = null; // unboxing label 571 nextParamLabel = new Label(); 572 573 for (int j = 0; j < primitiveTypes.length; j++) { 574 Class<?> c = primitiveTypes[j]; 575 if (canWidenTo(c, paramType)) { 576 if (l != null) { 577 l.bind(); 578 } 579 // Emit checking and unboxing code for this type 580 if (isConstructor) { 581 cb.opc_aload_2(); 582 } else { 583 cb.opc_aload_3(); 584 } 585 cb.opc_instanceof(indexForPrimitiveType(c)); 586 l = new Label(); 587 cb.opc_ifeq(l); 588 if (isConstructor) { 589 cb.opc_aload_2(); 590 } else { 591 cb.opc_aload_3(); 592 } 593 cb.opc_checkcast(indexForPrimitiveType(c)); 594 cb.opc_invokevirtual(unboxingMethodForPrimitiveType(c), 595 0, 596 typeSizeInStackSlots(c)); 597 emitWideningBytecodeForPrimitiveConversion(cb, 598 c, 599 paramType); 600 cb.opc_goto(nextParamLabel); 601 } 602 } 603 604 if (l == null) { 605 throw new InternalError 606 ("Must have found at least identity conversion"); 607 } 608 609 // Fell through; given object is null or invalid. According to 610 // the spec, we can throw IllegalArgumentException for both of 611 // these cases. 612 613 l.bind(); 614 cb.opc_new(illegalArgumentClass); 615 cb.opc_dup(); 616 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0); 617 cb.opc_athrow(); 618 } else { 619 // Emit appropriate checkcast 620 cb.opc_checkcast(paramTypeCPIdx); 621 paramTypeCPIdx = add(paramTypeCPIdx, S2); 622 // Fall through to next argument 623 } 624 } 625 // Bind last goto if present 626 if (nextParamLabel != null) { 627 nextParamLabel.bind(); 628 } 629 630 short invokeStartPC = cb.getLength(); 631 632 // OK, ready to perform the invocation. 633 if (isConstructor) { 634 cb.opc_invokespecial(targetMethodRef, count, 0); 635 } else { 636 if (isStatic()) { 637 cb.opc_invokestatic(targetMethodRef, 638 count, 639 typeSizeInStackSlots(returnType)); 640 } else { 641 if (isInterface()) { 642 if (isPrivate()) { 643 cb.opc_invokespecial(targetMethodRef, count, 0); 644 } else { 645 cb.opc_invokeinterface(targetMethodRef, 646 count, 647 count, 648 typeSizeInStackSlots(returnType)); 649 } 650 } else { 651 cb.opc_invokevirtual(targetMethodRef, 652 count, 653 typeSizeInStackSlots(returnType)); 654 } 655 } 656 } 657 658 short invokeEndPC = cb.getLength(); 659 660 if (!isConstructor) { 661 // Box return value if necessary 662 if (isPrimitive(returnType)) { 663 cb.opc_invokestatic(boxingMethodForPrimitiveType(returnType), 664 typeSizeInStackSlots(returnType), 665 0); 666 } else if (returnType == Void.TYPE) { 667 cb.opc_aconst_null(); 668 } 669 } 670 cb.opc_areturn(); 671 672 // We generate two exception handlers; one which is responsible 673 // for catching ClassCastException and NullPointerException and 674 // throwing IllegalArgumentException, and the other which catches 675 // all java/lang/Throwable objects thrown from the target method 676 // and wraps them in InvocationTargetExceptions. 677 678 short classCastHandler = cb.getLength(); 679 680 // ClassCast, etc. exception handler 681 cb.setStack(1); 682 cb.opc_invokespecial(toStringIdx, 0, 1); 683 cb.opc_new(illegalArgumentClass); 684 cb.opc_dup_x1(); 685 cb.opc_swap(); 686 cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0); 687 cb.opc_athrow(); 688 689 short invocationTargetHandler = cb.getLength(); 690 691 // InvocationTargetException exception handler 692 cb.setStack(1); 693 cb.opc_new(invocationTargetClass); 694 cb.opc_dup_x1(); 695 cb.opc_swap(); 696 cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0); 697 cb.opc_athrow(); 698 699 // Generate exception table. We cover the entire code sequence 700 // with an exception handler which catches ClassCastException and 701 // converts it into an IllegalArgumentException. 702 703 ClassFileAssembler exc = new ClassFileAssembler(); 704 705 exc.emitShort(illegalArgStartPC); // start PC 706 exc.emitShort(invokeStartPC); // end PC 707 exc.emitShort(classCastHandler); // handler PC 708 exc.emitShort(classCastClass); // catch type 709 710 exc.emitShort(illegalArgStartPC); // start PC 711 exc.emitShort(invokeStartPC); // end PC 712 exc.emitShort(classCastHandler); // handler PC 713 exc.emitShort(nullPointerClass); // catch type 714 715 exc.emitShort(invokeStartPC); // start PC 716 exc.emitShort(invokeEndPC); // end PC 717 exc.emitShort(invocationTargetHandler); // handler PC 718 exc.emitShort(throwableClass); // catch type 719 720 emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc, 721 new short[] { invocationTargetClass }); 722 } 723 724 private boolean usesPrimitiveTypes() { 725 // We need to emit boxing/unboxing constant pool information if 726 // the method takes a primitive type for any of its parameters or 727 // returns a primitive value (except void) 728 if (returnType.isPrimitive()) { 729 return true; 730 } 731 for (int i = 0; i < parameterTypes.length; i++) { 732 if (parameterTypes[i].isPrimitive()) { 733 return true; 734 } 735 } 736 return false; 737 } 738 739 private int numNonPrimitiveParameterTypes() { 740 int num = 0; 741 for (int i = 0; i < parameterTypes.length; i++) { 742 if (!parameterTypes[i].isPrimitive()) { 743 ++num; 744 } 745 } 746 return num; 747 } 748 749 private boolean isInterface() { 750 return declaringClass.isInterface(); 751 } 752 753 private String buildInternalSignature() { 754 StringBuilder sb = new StringBuilder(); 755 sb.append("("); 756 for (int i = 0; i < parameterTypes.length; i++) { 757 sb.append(getClassName(parameterTypes[i], true)); 758 } 759 sb.append(")"); 760 sb.append(getClassName(returnType, true)); 761 return sb.toString(); 762 } 763 764 private static synchronized String generateName(boolean isConstructor, 765 boolean forSerialization) 766 { 767 if (isConstructor) { 768 if (forSerialization) { 769 int num = ++serializationConstructorSymnum; 770 return "jdk/internal/reflect/GeneratedSerializationConstructorAccessor" + num; 771 } else { 772 int num = ++constructorSymnum; 773 return "jdk/internal/reflect/GeneratedConstructorAccessor" + num; 774 } 775 } else { 776 int num = ++methodSymnum; 777 return "jdk/internal/reflect/GeneratedMethodAccessor" + num; 778 } 779 } 780 }