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