< prev index next >

src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java

Print this page

 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.invoke;
 27 
 28 import jdk.internal.misc.CDS;
 29 import jdk.internal.org.objectweb.asm.*;
 30 import sun.invoke.util.BytecodeDescriptor;
 31 import sun.invoke.util.VerifyAccess;
 32 import sun.security.action.GetPropertyAction;
 33 import sun.security.action.GetBooleanAction;
 34 
 35 import java.io.FilePermission;
 36 import java.io.Serializable;
 37 import java.lang.constant.ConstantDescs;
 38 import java.lang.invoke.MethodHandles.Lookup;
 39 import java.lang.reflect.Modifier;
 40 import java.security.AccessController;
 41 import java.security.PrivilegedAction;

 42 import java.util.LinkedHashSet;
 43 import java.util.concurrent.atomic.AtomicInteger;
 44 import java.util.PropertyPermission;
 45 import java.util.Set;
 46 
 47 import static java.lang.invoke.MethodHandleStatics.CLASSFILE_VERSION;
 48 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
 49 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
 50 import static java.lang.invoke.MethodType.methodType;
 51 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 52 
 53 /**
 54  * Lambda metafactory implementation which dynamically creates an
 55  * inner-class-like class per lambda callsite.
 56  *
 57  * @see LambdaMetafactory
 58  */
 59 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
 60     private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
 61     private static final String JAVA_LANG_OBJECT = "java/lang/Object";

340 
341         // Forward the SAM method
342         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
343                                           interfaceMethodType.toMethodDescriptorString(), null, null);
344         new ForwardingMethodGenerator(mv).generate(interfaceMethodType);
345 
346         // Forward the altMethods
347         if (altMethods != null) {
348             for (MethodType mt : altMethods) {
349                 mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
350                                     mt.toMethodDescriptorString(), null, null);
351                 new ForwardingMethodGenerator(mv).generate(mt);
352             }
353         }
354 
355         if (isSerializable)
356             generateSerializationFriendlyMethods();
357         else if (accidentallySerializable)
358             generateSerializationHostileMethods();
359 










360         cw.visitEnd();
361 
362         // Define the generated class in this VM.
363 
364         final byte[] classBytes = cw.toByteArray();
365         // If requested, dump out to a file for debugging purposes
366         if (dumper != null) {
367             AccessController.doPrivileged(new PrivilegedAction<>() {
368                 @Override
369                 public Void run() {
370                     dumper.dumpClass(lambdaClassName, classBytes);
371                     return null;
372                 }
373             }, null,
374             new FilePermission("<<ALL FILES>>", "read, write"),
375             // createDirectories may need it
376             new PropertyPermission("user.dir", "read"));
377         }
378         try {
379             // this class is linked at the indy callsite; so define a hidden nestmate

573             for (int i = 0; i < samParametersLength; i++) {
574                 Class<?> argType = samType.parameterType(i);
575                 visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
576                 lvIndex += getParameterSize(argType);
577                 convertType(argType, implMethodType.parameterType(captureArity + i), dynamicMethodType.parameterType(i));
578             }
579         }
580 
581         private int invocationOpcode() throws InternalError {
582             return switch (implKind) {
583                 case MethodHandleInfo.REF_invokeStatic     -> INVOKESTATIC;
584                 case MethodHandleInfo.REF_newInvokeSpecial -> INVOKESPECIAL;
585                 case MethodHandleInfo.REF_invokeVirtual    -> INVOKEVIRTUAL;
586                 case MethodHandleInfo.REF_invokeInterface  -> INVOKEINTERFACE;
587                 case MethodHandleInfo.REF_invokeSpecial    -> INVOKESPECIAL;
588                 default -> throw new InternalError("Unexpected invocation kind: " + implKind);
589             };
590         }
591     }
592 


































































593     static int getParameterSize(Class<?> c) {
594         if (c == Void.TYPE) {
595             return 0;
596         } else if (c == Long.TYPE || c == Double.TYPE) {
597             return 2;
598         }
599         return 1;
600     }
601 
602     static int getLoadOpcode(Class<?> c) {
603         if(c == Void.TYPE) {
604             throw new InternalError("Unexpected void type of load opcode");
605         }
606         return ILOAD + getOpcodeOffset(c);
607     }
608 
609     static int getReturnOpcode(Class<?> c) {
610         if(c == Void.TYPE) {
611             return RETURN;
612         }

 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.invoke;
 27 
 28 import jdk.internal.misc.CDS;
 29 import jdk.internal.org.objectweb.asm.*;
 30 import sun.invoke.util.BytecodeDescriptor;
 31 import sun.invoke.util.VerifyAccess;
 32 import sun.security.action.GetPropertyAction;
 33 import sun.security.action.GetBooleanAction;
 34 
 35 import java.io.FilePermission;
 36 import java.io.Serializable;
 37 import java.lang.constant.ConstantDescs;
 38 import java.lang.invoke.MethodHandles.Lookup;
 39 import java.lang.reflect.Modifier;
 40 import java.security.AccessController;
 41 import java.security.PrivilegedAction;
 42 import java.util.HashSet;
 43 import java.util.LinkedHashSet;
 44 import java.util.concurrent.atomic.AtomicInteger;
 45 import java.util.PropertyPermission;
 46 import java.util.Set;
 47 
 48 import static java.lang.invoke.MethodHandleStatics.CLASSFILE_VERSION;
 49 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
 50 import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
 51 import static java.lang.invoke.MethodType.methodType;
 52 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 53 
 54 /**
 55  * Lambda metafactory implementation which dynamically creates an
 56  * inner-class-like class per lambda callsite.
 57  *
 58  * @see LambdaMetafactory
 59  */
 60 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
 61     private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
 62     private static final String JAVA_LANG_OBJECT = "java/lang/Object";

341 
342         // Forward the SAM method
343         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
344                                           interfaceMethodType.toMethodDescriptorString(), null, null);
345         new ForwardingMethodGenerator(mv).generate(interfaceMethodType);
346 
347         // Forward the altMethods
348         if (altMethods != null) {
349             for (MethodType mt : altMethods) {
350                 mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
351                                     mt.toMethodDescriptorString(), null, null);
352                 new ForwardingMethodGenerator(mv).generate(mt);
353             }
354         }
355 
356         if (isSerializable)
357             generateSerializationFriendlyMethods();
358         else if (accidentallySerializable)
359             generateSerializationHostileMethods();
360 
361         // generate Preload attribute if it references any value class
362         PreloadAttributeBuilder builder = new PreloadAttributeBuilder(targetClass);
363         builder.add(factoryType)
364                .add(interfaceMethodType)
365                .add(implMethodType)
366                .add(dynamicMethodType)
367                .add(altMethods);
368         if (!builder.isEmpty())
369             cw.visitAttribute(builder.build());
370 
371         cw.visitEnd();
372 
373         // Define the generated class in this VM.
374 
375         final byte[] classBytes = cw.toByteArray();
376         // If requested, dump out to a file for debugging purposes
377         if (dumper != null) {
378             AccessController.doPrivileged(new PrivilegedAction<>() {
379                 @Override
380                 public Void run() {
381                     dumper.dumpClass(lambdaClassName, classBytes);
382                     return null;
383                 }
384             }, null,
385             new FilePermission("<<ALL FILES>>", "read, write"),
386             // createDirectories may need it
387             new PropertyPermission("user.dir", "read"));
388         }
389         try {
390             // this class is linked at the indy callsite; so define a hidden nestmate

584             for (int i = 0; i < samParametersLength; i++) {
585                 Class<?> argType = samType.parameterType(i);
586                 visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
587                 lvIndex += getParameterSize(argType);
588                 convertType(argType, implMethodType.parameterType(captureArity + i), dynamicMethodType.parameterType(i));
589             }
590         }
591 
592         private int invocationOpcode() throws InternalError {
593             return switch (implKind) {
594                 case MethodHandleInfo.REF_invokeStatic     -> INVOKESTATIC;
595                 case MethodHandleInfo.REF_newInvokeSpecial -> INVOKESPECIAL;
596                 case MethodHandleInfo.REF_invokeVirtual    -> INVOKEVIRTUAL;
597                 case MethodHandleInfo.REF_invokeInterface  -> INVOKEINTERFACE;
598                 case MethodHandleInfo.REF_invokeSpecial    -> INVOKESPECIAL;
599                 default -> throw new InternalError("Unexpected invocation kind: " + implKind);
600             };
601         }
602     }
603 
604     /*
605      * Preload attribute builder
606      */
607     static class PreloadAttributeBuilder {
608         private final Set<Class<?>> preloadClasses = new HashSet<>();
609         PreloadAttributeBuilder(Class<?> targetClass) {
610             if (requiresPreload(targetClass)) {
611                 preloadClasses.add(targetClass);
612             }
613         }
614 
615         /*
616          * Add the value types referenced in the given MethodType.
617          */
618         PreloadAttributeBuilder add(MethodType mt) {
619             // parameter types
620             for (Class<?> paramType : mt.ptypes()) {
621                 if (requiresPreload(paramType)) {
622                     preloadClasses.add(paramType);
623                 }
624             }
625             // return type
626             if (requiresPreload(mt.returnType())) {
627                 preloadClasses.add(mt.returnType());
628             }
629             return this;
630         }
631 
632         PreloadAttributeBuilder add(MethodType... mtypes) {
633             for (MethodType mt : mtypes) {
634                 add(mt);
635             }
636             return this;
637         }
638 
639         boolean requiresPreload(Class<?> cls) {
640             Class<?> c = cls;
641             while (c.isArray()) {
642                 c = c.getComponentType();
643             }
644             return (c.isValue() && !c.isPrimitiveClass()) || c.isPrimitiveValueType();
645         }
646 
647         boolean isEmpty() {
648             return preloadClasses.isEmpty();
649         }
650 
651         Attribute build() {
652             return new Attribute("Preload") {
653                 @Override
654                 protected ByteVector write(ClassWriter cw,
655                                            byte[] code,
656                                            int len,
657                                            int maxStack,
658                                            int maxLocals) {
659                     ByteVector attr = new ByteVector();
660                     attr.putShort(preloadClasses.size());
661                     for (Class<?> c : preloadClasses) {
662                         attr.putShort(cw.newClass(Type.getInternalName(c)));
663                     }
664                     return attr;
665                 }
666             };
667         }
668     }
669 
670     static int getParameterSize(Class<?> c) {
671         if (c == Void.TYPE) {
672             return 0;
673         } else if (c == Long.TYPE || c == Double.TYPE) {
674             return 2;
675         }
676         return 1;
677     }
678 
679     static int getLoadOpcode(Class<?> c) {
680         if(c == Void.TYPE) {
681             throw new InternalError("Unexpected void type of load opcode");
682         }
683         return ILOAD + getOpcodeOffset(c);
684     }
685 
686     static int getReturnOpcode(Class<?> c) {
687         if(c == Void.TYPE) {
688             return RETURN;
689         }
< prev index next >