< prev index next >

src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java

Print this page

 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

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 

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

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 

 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.isPrimitiveClass();
 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

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 

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

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 
< prev index next >