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