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