< prev index next >

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

Print this page

  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 
 32 /** Generator for jdk.internal.reflect.SerializationConstructorAccessorImpl
 33     objects using bytecodes to implement a constructor for serialization
 34     returned by ReflectionFactory::newConstructorForSerialization. */
 35 
 36 class SerializationConstructorAccessorGenerator extends AccessorGenerator {
 37 
 38     private static final short NUM_BASE_CPOOL_ENTRIES   = (short) 12;
 39     // One for invoke() plus one for constructor
 40     private static final short NUM_METHODS              = (short) 2;
 41     // Only used if forSerialization is true
 42     private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2;
 43 
 44     private static volatile int methodSymnum;
 45     private static volatile int constructorSymnum;
 46     private static volatile int serializationConstructorSymnum;
 47 
 48     private Class<?>   declaringClass;
 49     private Class<?>[] parameterTypes;
 50     private Class<?>   returnType;
 51     private boolean    isConstructor;

 52     private boolean    forSerialization;
 53 
 54     private short targetMethodRef;
 55     private short invokeIdx;
 56     private short invokeDescriptorIdx;
 57     // Constant pool index of CONSTANT_Class_info for first
 58     // non-primitive parameter type. Should be incremented by 2.
 59     private short nonPrimitiveParametersBaseIdx;
 60 
 61     SerializationConstructorAccessorGenerator() {
 62     }
 63 
 64     /** This routine is not thread-safe */
 65     public SerializationConstructorAccessorImpl
 66     generateSerializationConstructor(Class<?> declaringClass,
 67                                      Class<?>[] parameterTypes,
 68                                      int modifiers,
 69                                      Class<?> targetConstructorClass)
 70     {

 71         return (SerializationConstructorAccessorImpl)
 72             generate(declaringClass,
 73                      "<init>",
 74                      parameterTypes,
 75                      Void.TYPE,
 76                      modifiers,
 77                      true,

 78                      true,
 79                      targetConstructorClass);
 80     }
 81 
 82     /** This routine is not thread-safe */
 83     @SuppressWarnings("removal")
 84     private MagicAccessorImpl generate(final Class<?> declaringClass,
 85                                        String name,
 86                                        Class<?>[] parameterTypes,
 87                                        Class<?>   returnType,
 88                                        int modifiers,
 89                                        boolean isConstructor,

 90                                        boolean forSerialization,
 91                                        Class<?> serializationTargetClass)
 92     {
 93         ByteVector vec = ByteVectorFactory.create();
 94         asm = new ClassFileAssembler(vec);
 95         this.declaringClass = declaringClass;
 96         this.parameterTypes = parameterTypes;
 97         this.returnType = returnType;
 98         this.modifiers = modifiers;
 99         this.isConstructor = isConstructor;

100         this.forSerialization = forSerialization;
101 
102         asm.emitMagicAndVersion();
103 
104         // Constant pool entries:
105         // ( * = Boxing information: optional)
106         // (+  = Shared entries provided by AccessorGenerator)
107         // (^  = Only present if generating SerializationConstructorAccessor)
108         //     [UTF-8] [This class's name]
109         //     [CONSTANT_Class_info] for above
110         //     [UTF-8] "jdk/internal/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
111         //     [CONSTANT_Class_info] for above
112         //     [UTF-8] [Target class's name]
113         //     [CONSTANT_Class_info] for above
114         // ^   [UTF-8] [Serialization: Class's name in which to invoke constructor]
115         // ^   [CONSTANT_Class_info] for above
116         //     [UTF-8] target method or constructor name
117         //     [UTF-8] target method or constructor signature
118         //     [CONSTANT_NameAndType_info] for above
119         //     [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method

282         targetMethodRef = asm.cpi();
283         if (isConstructor) {
284             asm.emitConstantPoolUTF8("newInstance");
285         } else {
286             asm.emitConstantPoolUTF8("invoke");
287         }
288         invokeIdx = asm.cpi();
289         if (isConstructor) {
290             asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
291         } else {
292             asm.emitConstantPoolUTF8
293                 ("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
294         }
295         invokeDescriptorIdx = asm.cpi();
296 
297         // Output class information for non-primitive parameter types
298         nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
299         for (int i = 0; i < parameterTypes.length; i++) {
300             Class<?> c = parameterTypes[i];
301             if (!isPrimitive(c)) {
302                 asm.emitConstantPoolUTF8(getClassName(c, false));
303                 asm.emitConstantPoolClass(asm.cpi());
304             }
305         }
306 
307         // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
308         emitCommonConstantPoolEntries();
309 
310         // Boxing entries
311         if (usesPrimitives) {
312             emitBoxingContantPoolEntries();
313         }
314 
315         if (asm.cpi() != numCPEntries) {
316             throw new InternalError("Adjust this code (cpi = " + asm.cpi() +
317                                     ", numCPEntries = " + numCPEntries + ")");
318         }
319 
320         // Access flags
321         asm.emitShort(ACC_PUBLIC);
322 

372     private void emitInvoke() {
373         // NOTE that this code will only handle 65535 parameters since we
374         // use the sipush instruction to get the array index on the
375         // operand stack.
376         if (parameterTypes.length > 65535) {
377             throw new InternalError("Can't handle more than 65535 parameters");
378         }
379 
380         // Generate code into fresh code buffer
381         ClassFileAssembler cb = new ClassFileAssembler();
382         if (isConstructor) {
383             // 1 incoming argument
384             cb.setMaxLocals(2);
385         } else {
386             // 2 incoming arguments
387             cb.setMaxLocals(3);
388         }
389 
390         short illegalArgStartPC = 0;
391 
392         if (isConstructor) {
393             // Instantiate target class before continuing
394             // new <target class type>
395             // dup
396             cb.opc_new(targetClass);
397             cb.opc_dup();
398         } else {
399             // Get target object on operand stack if necessary.
400 
401             // We need to do an explicit null check here; we won't see
402             // NullPointerExceptions from the invoke bytecode, since it's
403             // covered by an exception handler.
404             if (!isStatic()) {
405                 // aload_1
406                 // ifnonnull <checkcast label>
407                 // new <NullPointerException>
408                 // dup
409                 // invokespecial <NullPointerException ctor>
410                 // athrow
411                 // <checkcast label:>
412                 // aload_1

562                 l.bind();
563                 cb.opc_new(illegalArgumentClass);
564                 cb.opc_dup();
565                 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
566                 cb.opc_athrow();
567             } else {
568                 // Emit appropriate checkcast
569                 cb.opc_checkcast(paramTypeCPIdx);
570                 paramTypeCPIdx = add(paramTypeCPIdx, S2);
571                 // Fall through to next argument
572             }
573         }
574         // Bind last goto if present
575         if (nextParamLabel != null) {
576             nextParamLabel.bind();
577         }
578 
579         short invokeStartPC = cb.getLength();
580 
581         // OK, ready to perform the invocation.
582         if (isConstructor) {
583             cb.opc_invokespecial(targetMethodRef, count, 0);
584         } else {
585             if (isStatic()) {
586                 cb.opc_invokestatic(targetMethodRef,
587                                     count,
588                                     typeSizeInStackSlots(returnType));
589             } else {
590                 if (isInterface()) {
591                     cb.opc_invokeinterface(targetMethodRef,
592                                            count,
593                                            count,
594                                            typeSizeInStackSlots(returnType));
595                 } else {
596                     cb.opc_invokevirtual(targetMethodRef,
597                                          count,
598                                          typeSizeInStackSlots(returnType));
599                 }
600             }
601         }
602 

  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 
 34 /** Generator for jdk.internal.reflect.SerializationConstructorAccessorImpl
 35     objects using bytecodes to implement a constructor for serialization
 36     returned by ReflectionFactory::newConstructorForSerialization. */
 37 
 38 class SerializationConstructorAccessorGenerator extends AccessorGenerator {
 39 
 40     private static final short NUM_BASE_CPOOL_ENTRIES   = (short) 12;
 41     // One for invoke() plus one for constructor
 42     private static final short NUM_METHODS              = (short) 2;
 43     // Only used if forSerialization is true
 44     private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2;
 45 
 46     private static volatile int methodSymnum;
 47     private static volatile int constructorSymnum;
 48     private static volatile int serializationConstructorSymnum;
 49 
 50     private Class<?>   declaringClass;
 51     private Class<?>[] parameterTypes;
 52     private Class<?>   returnType;
 53     private boolean    isConstructor;
 54     private boolean    isStaticFactory;
 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     SerializationConstructorAccessorGenerator() {
 65     }
 66 
 67     /** This routine is not thread-safe */
 68     public SerializationConstructorAccessorImpl
 69     generateSerializationConstructor(Class<?> declaringClass,
 70                                      Class<?>[] parameterTypes,
 71                                      int modifiers,
 72                                      Class<?> targetConstructorClass)
 73     {
 74         boolean isStaticFactory = declaringClass.isValue();
 75         return (SerializationConstructorAccessorImpl)
 76             generate(declaringClass,
 77                      "<init>",
 78                      parameterTypes,
 79                      isStaticFactory ? PrimitiveClass.asValueType(declaringClass) : Void.TYPE,
 80                      modifiers,
 81                      true,
 82                      isStaticFactory,
 83                      true,
 84                      targetConstructorClass);
 85     }
 86 
 87     /** This routine is not thread-safe */
 88     @SuppressWarnings("removal")
 89     private MagicAccessorImpl generate(final Class<?> declaringClass,
 90                                        String name,
 91                                        Class<?>[] parameterTypes,
 92                                        Class<?>   returnType,
 93                                        int modifiers,
 94                                        boolean isConstructor,
 95                                        boolean isStaticFactory,
 96                                        boolean forSerialization,
 97                                        Class<?> serializationTargetClass)
 98     {
 99         ByteVector vec = ByteVectorFactory.create();
100         asm = new ClassFileAssembler(vec);
101         this.declaringClass = declaringClass;
102         this.parameterTypes = parameterTypes;
103         this.returnType = returnType;
104         this.modifiers = modifiers;
105         this.isConstructor = isConstructor;
106         this.isStaticFactory = isStaticFactory;
107         this.forSerialization = forSerialization;
108 
109         asm.emitMagicAndVersion();
110 
111         // Constant pool entries:
112         // ( * = Boxing information: optional)
113         // (+  = Shared entries provided by AccessorGenerator)
114         // (^  = Only present if generating SerializationConstructorAccessor)
115         //     [UTF-8] [This class's name]
116         //     [CONSTANT_Class_info] for above
117         //     [UTF-8] "jdk/internal/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
118         //     [CONSTANT_Class_info] for above
119         //     [UTF-8] [Target class's name]
120         //     [CONSTANT_Class_info] for above
121         // ^   [UTF-8] [Serialization: Class's name in which to invoke constructor]
122         // ^   [CONSTANT_Class_info] for above
123         //     [UTF-8] target method or constructor name
124         //     [UTF-8] target method or constructor signature
125         //     [CONSTANT_NameAndType_info] for above
126         //     [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method

289         targetMethodRef = asm.cpi();
290         if (isConstructor) {
291             asm.emitConstantPoolUTF8("newInstance");
292         } else {
293             asm.emitConstantPoolUTF8("invoke");
294         }
295         invokeIdx = asm.cpi();
296         if (isConstructor) {
297             asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
298         } else {
299             asm.emitConstantPoolUTF8
300                 ("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
301         }
302         invokeDescriptorIdx = asm.cpi();
303 
304         // Output class information for non-primitive parameter types
305         nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
306         for (int i = 0; i < parameterTypes.length; i++) {
307             Class<?> c = parameterTypes[i];
308             if (!isPrimitive(c)) {
309                 asm.emitConstantPoolUTF8(getClassName(c, true));
310                 asm.emitConstantPoolClass(asm.cpi());
311             }
312         }
313 
314         // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
315         emitCommonConstantPoolEntries();
316 
317         // Boxing entries
318         if (usesPrimitives) {
319             emitBoxingContantPoolEntries();
320         }
321 
322         if (asm.cpi() != numCPEntries) {
323             throw new InternalError("Adjust this code (cpi = " + asm.cpi() +
324                                     ", numCPEntries = " + numCPEntries + ")");
325         }
326 
327         // Access flags
328         asm.emitShort(ACC_PUBLIC);
329 

379     private void emitInvoke() {
380         // NOTE that this code will only handle 65535 parameters since we
381         // use the sipush instruction to get the array index on the
382         // operand stack.
383         if (parameterTypes.length > 65535) {
384             throw new InternalError("Can't handle more than 65535 parameters");
385         }
386 
387         // Generate code into fresh code buffer
388         ClassFileAssembler cb = new ClassFileAssembler();
389         if (isConstructor) {
390             // 1 incoming argument
391             cb.setMaxLocals(2);
392         } else {
393             // 2 incoming arguments
394             cb.setMaxLocals(3);
395         }
396 
397         short illegalArgStartPC = 0;
398 
399         if (isConstructor && !isStaticFactory) {
400             // Instantiate target class before continuing
401             // new <target class type>
402             // dup
403             cb.opc_new(targetClass);
404             cb.opc_dup();
405         } else {
406             // Get target object on operand stack if necessary.
407 
408             // We need to do an explicit null check here; we won't see
409             // NullPointerExceptions from the invoke bytecode, since it's
410             // covered by an exception handler.
411             if (!isStatic()) {
412                 // aload_1
413                 // ifnonnull <checkcast label>
414                 // new <NullPointerException>
415                 // dup
416                 // invokespecial <NullPointerException ctor>
417                 // athrow
418                 // <checkcast label:>
419                 // aload_1

569                 l.bind();
570                 cb.opc_new(illegalArgumentClass);
571                 cb.opc_dup();
572                 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
573                 cb.opc_athrow();
574             } else {
575                 // Emit appropriate checkcast
576                 cb.opc_checkcast(paramTypeCPIdx);
577                 paramTypeCPIdx = add(paramTypeCPIdx, S2);
578                 // Fall through to next argument
579             }
580         }
581         // Bind last goto if present
582         if (nextParamLabel != null) {
583             nextParamLabel.bind();
584         }
585 
586         short invokeStartPC = cb.getLength();
587 
588         // OK, ready to perform the invocation.
589         if (isConstructor && !isStaticFactory) {
590             cb.opc_invokespecial(targetMethodRef, count, 0);
591         } else {
592             if (isStatic()) {
593                 cb.opc_invokestatic(targetMethodRef,
594                                     count,
595                                     typeSizeInStackSlots(returnType));
596             } else {
597                 if (isInterface()) {
598                     cb.opc_invokeinterface(targetMethodRef,
599                                            count,
600                                            count,
601                                            typeSizeInStackSlots(returnType));
602                 } else {
603                     cb.opc_invokevirtual(targetMethodRef,
604                                          count,
605                                          typeSizeInStackSlots(returnType));
606                 }
607             }
608         }
609 
< prev index next >