jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
changeset 14762 34956da26ceb
parent 14680 aa760c2a931a
child 16001 fd4c8d3becf8
equal deleted inserted replaced
14761:b31f1eaee88a 14762:34956da26ceb
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package java.lang.invoke;
    26 package java.lang.invoke;
    27 
    27 
    28 import java.io.FileOutputStream;
    28 import java.lang.reflect.Constructor;
    29 import java.io.IOException;
       
    30 import java.lang.reflect.Method;
    29 import java.lang.reflect.Method;
    31 import java.security.ProtectionDomain;
    30 import java.security.ProtectionDomain;
    32 import java.util.concurrent.atomic.AtomicInteger;
    31 import java.util.concurrent.atomic.AtomicInteger;
    33 import sun.util.logging.PlatformLogger;
       
    34 import jdk.internal.org.objectweb.asm.*;
    32 import jdk.internal.org.objectweb.asm.*;
    35 import static jdk.internal.org.objectweb.asm.Opcodes.*;
    33 import static jdk.internal.org.objectweb.asm.Opcodes.*;
    36 import sun.misc.Unsafe;
    34 import sun.misc.Unsafe;
       
    35 import java.security.AccessController;
       
    36 import java.security.PrivilegedAction;
    37 
    37 
    38 /**
    38 /**
    39  * InnerClassLambdaMetafactory
    39  * InnerClassLambdaMetafactory
    40  */
    40  */
    41 /*non-public*/ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
    41 /*non-public*/ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
   118      * of the class which the CallSite will return, otherwise, generate handles
   118      * of the class which the CallSite will return, otherwise, generate handles
   119      * which will call the class' constructor.
   119      * which will call the class' constructor.
   120      *
   120      *
   121      * @return a CallSite, which, when invoked, will return an instance of the
   121      * @return a CallSite, which, when invoked, will return an instance of the
   122      * functional interface
   122      * functional interface
   123      * @throws ReflectiveOperationException
   123      * @throws ReflectiveOperationException, LambdaConversionException
   124      */
   124      */
   125     @Override
   125     @Override
   126     CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException {
   126     CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException {
   127         final Class<?> innerClass = spinInnerClass();
   127         final Class<?> innerClass = spinInnerClass();
   128         if (invokedType.parameterCount() == 0) {
   128         if (invokedType.parameterCount() == 0) {
   129             return new ConstantCallSite(MethodHandles.constant(samBase, innerClass.newInstance()));
   129             final Constructor[] ctrs = AccessController.doPrivileged(
       
   130                     new PrivilegedAction<Constructor[]>() {
       
   131                 @Override
       
   132                 public Constructor[] run() {
       
   133                     return innerClass.getDeclaredConstructors();
       
   134                 }
       
   135             });
       
   136             if (ctrs.length != 1) {
       
   137                 throw new ReflectiveOperationException("Expected one lambda constructor for "
       
   138                         + innerClass.getCanonicalName() + ", got " + ctrs.length);
       
   139             }
       
   140             // The lambda implementing inner class constructor is private, set
       
   141             // it accessible (by us) before creating the constant sole instance
       
   142             AccessController.doPrivileged(new PrivilegedAction<Void>() {
       
   143                 @Override
       
   144                 public Void run() {
       
   145                     ctrs[0].setAccessible(true);
       
   146                     return null;
       
   147                 }
       
   148             });
       
   149             Object inst = ctrs[0].newInstance();
       
   150             return new ConstantCallSite(MethodHandles.constant(samBase, inst));
   130         } else {
   151         } else {
   131             return new ConstantCallSite(
   152             return new ConstantCallSite(
   132                     MethodHandles.Lookup.IMPL_LOOKUP
   153                     MethodHandles.Lookup.IMPL_LOOKUP
   133                     .findConstructor(innerClass, constructorType)
   154                     .findConstructor(innerClass, constructorType)
   134                     .asType(constructorType.changeReturnType(samBase)));
   155                     .asType(constructorType.changeReturnType(samBase)));
   142      * @return a Class which implements the functional interface
   163      * @return a Class which implements the functional interface
   143      */
   164      */
   144     private <T> Class<? extends T> spinInnerClass() throws LambdaConversionException {
   165     private <T> Class<? extends T> spinInnerClass() throws LambdaConversionException {
   145         String samName = samBase.getName().replace('.', '/');
   166         String samName = samBase.getName().replace('.', '/');
   146 
   167 
   147         cw.visit(CLASSFILE_VERSION, ACC_PUBLIC + ACC_SUPER, lambdaClassName, null, NAME_MAGIC_ACCESSOR_IMPL,
   168         cw.visit(CLASSFILE_VERSION, ACC_SUPER, lambdaClassName, null, NAME_MAGIC_ACCESSOR_IMPL,
   148                  isSerializable ? new String[]{samName, NAME_SERIALIZABLE} : new String[]{samName});
   169                  isSerializable ? new String[]{samName, NAME_SERIALIZABLE} : new String[]{samName});
   149 
   170 
   150         // Generate final fields to be filled in by constructor
   171         // Generate final fields to be filled in by constructor
   151         for (int i = 0; i < argTypes.length; i++) {
   172         for (int i = 0; i < argTypes.length; i++) {
   152             FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(), null, null);
   173             FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(), null, null);
   184 
   205 
   185         // Define the generated class in this VM.
   206         // Define the generated class in this VM.
   186 
   207 
   187         final byte[] classBytes = cw.toByteArray();
   208         final byte[] classBytes = cw.toByteArray();
   188 
   209 
   189         if (System.getProperty("debug.dump.generated") != null) {
   210         /*** Uncomment to dump the generated file
   190             System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName, classBytes.length);
   211             System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName, classBytes.length);
   191             try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) {
   212             try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) {
   192                 fos.write(classBytes);
   213                 fos.write(classBytes);
   193             } catch (IOException ex) {
   214             } catch (IOException ex) {
   194                 PlatformLogger.getLogger(InnerClassLambdaMetafactory.class.getName()).severe(ex.getMessage(), ex);
   215                 Logger.getLogger(InnerClassLambdaMetafactory.class.getName()).log(Level.SEVERE, null, ex);
   195             }
   216             }
   196         }
   217         ***/
   197 
   218 
   198         ClassLoader loader = targetClass.getClassLoader();
   219         ClassLoader loader = targetClass.getClassLoader();
   199         ProtectionDomain pd = (loader == null) ? null : targetClass.getProtectionDomain();
   220         ProtectionDomain pd = (loader == null)
       
   221             ? null
       
   222             : AccessController.doPrivileged(
       
   223             new PrivilegedAction<ProtectionDomain>() {
       
   224                 @Override
       
   225                 public ProtectionDomain run() {
       
   226                     return targetClass.getProtectionDomain();
       
   227                 }
       
   228             }
       
   229         );
       
   230 
   200         return (Class<? extends T>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length, loader, pd);
   231         return (Class<? extends T>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length, loader, pd);
   201     }
   232     }
   202 
   233 
   203     /**
   234     /**
   204      * Generate the constructor for the class
   235      * Generate the constructor for the class
   205      */
   236      */
   206     private void generateConstructor() {
   237     private void generateConstructor() {
   207         // Generate constructor
   238         // Generate constructor
   208         MethodVisitor ctor = cw.visitMethod(ACC_PUBLIC, NAME_CTOR, constructorDesc, null, null);
   239         MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, constructorDesc, null, null);
   209         ctor.visitCode();
   240         ctor.visitCode();
   210         ctor.visitVarInsn(ALOAD, 0);
   241         ctor.visitVarInsn(ALOAD, 0);
   211         ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, METHOD_DESCRIPTOR_VOID);
   242         ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, METHOD_DESCRIPTOR_VOID);
   212         int lvIndex = 0;
   243         int lvIndex = 0;
   213         for (int i = 0; i < argTypes.length; i++) {
   244         for (int i = 0; i < argTypes.length; i++) {