< prev index next >

src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.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 java.lang.invoke;
  27 


  28 import jdk.internal.org.objectweb.asm.*;
  29 import sun.invoke.util.BytecodeDescriptor;
  30 import jdk.internal.misc.Unsafe;
  31 import sun.security.action.GetPropertyAction;
  32 
  33 import java.io.FilePermission;
  34 import java.io.Serializable;
  35 import java.lang.reflect.Constructor;
  36 import java.security.AccessController;
  37 import java.security.PrivilegedAction;

  38 import java.util.LinkedHashSet;
  39 import java.util.concurrent.atomic.AtomicInteger;
  40 import java.util.PropertyPermission;
  41 import java.util.Set;
  42 
  43 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  44 
  45 /**
  46  * Lambda metafactory implementation which dynamically creates an
  47  * inner-class-like class per lambda callsite.
  48  *
  49  * @see LambdaMetafactory
  50  */
  51 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
  52     private static final Unsafe UNSAFE = Unsafe.getUnsafe();

  53 
  54     private static final int CLASSFILE_VERSION = 52;
  55     private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
  56     private static final String JAVA_LANG_OBJECT = "java/lang/Object";
  57     private static final String NAME_CTOR = "<init>";
  58     private static final String NAME_FACTORY = "get$Lambda";
  59 
  60     //Serialization support
  61     private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
  62     private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
  63     private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
  64     private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
  65     private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
  66     private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
  67     private static final String NAME_METHOD_READ_OBJECT = "readObject";
  68     private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
  69 
  70     private static final String DESCR_CLASS = "Ljava/lang/Class;";
  71     private static final String DESCR_STRING = "Ljava/lang/String;";
  72     private static final String DESCR_OBJECT = "Ljava/lang/Object;";


 280         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
 281                                           samMethodType.toMethodDescriptorString(), null, null);
 282         mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
 283         new ForwardingMethodGenerator(mv).generate(samMethodType);
 284 
 285         // Forward the bridges
 286         if (additionalBridges != null) {
 287             for (MethodType mt : additionalBridges) {
 288                 mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
 289                                     mt.toMethodDescriptorString(), null, null);
 290                 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
 291                 new ForwardingMethodGenerator(mv).generate(mt);
 292             }
 293         }
 294 
 295         if (isSerializable)
 296             generateSerializationFriendlyMethods();
 297         else if (accidentallySerializable)
 298             generateSerializationHostileMethods();
 299 












 300         cw.visitEnd();
 301 
 302         // Define the generated class in this VM.
 303 
 304         final byte[] classBytes = cw.toByteArray();
 305 
 306         // If requested, dump out to a file for debugging purposes
 307         if (dumper != null) {
 308             AccessController.doPrivileged(new PrivilegedAction<>() {
 309                 @Override
 310                 public Void run() {
 311                     dumper.dumpClass(lambdaClassName, classBytes);
 312                     return null;
 313                 }
 314             }, null,
 315             new FilePermission("<<ALL FILES>>", "read, write"),
 316             // createDirectories may need it
 317             new PropertyPermission("user.dir", "read"));
 318         }
 319 


 528             return RETURN;
 529         }
 530         return IRETURN + getOpcodeOffset(c);
 531     }
 532 
 533     private static int getOpcodeOffset(Class<?> c) {
 534         if (c.isPrimitive()) {
 535             if (c == Long.TYPE) {
 536                 return 1;
 537             } else if (c == Float.TYPE) {
 538                 return 2;
 539             } else if (c == Double.TYPE) {
 540                 return 3;
 541             }
 542             return 0;
 543         } else {
 544             return 4;
 545         }
 546     }
 547 






























































 548 }


   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 java.lang.invoke;
  27 
  28 import jdk.internal.misc.JavaLangAccess;
  29 import jdk.internal.misc.SharedSecrets;
  30 import jdk.internal.org.objectweb.asm.*;
  31 import sun.invoke.util.BytecodeDescriptor;
  32 import jdk.internal.misc.Unsafe;
  33 import sun.security.action.GetPropertyAction;
  34 
  35 import java.io.FilePermission;
  36 import java.io.Serializable;
  37 import java.lang.reflect.Constructor;
  38 import java.security.AccessController;
  39 import java.security.PrivilegedAction;
  40 import java.util.HashSet;
  41 import java.util.LinkedHashSet;
  42 import java.util.concurrent.atomic.AtomicInteger;
  43 import java.util.PropertyPermission;
  44 import java.util.Set;
  45 
  46 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  47 
  48 /**
  49  * Lambda metafactory implementation which dynamically creates an
  50  * inner-class-like class per lambda callsite.
  51  *
  52  * @see LambdaMetafactory
  53  */
  54 /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
  55     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
  56     private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
  57 
  58     private static final int CLASSFILE_VERSION = 52;
  59     private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
  60     private static final String JAVA_LANG_OBJECT = "java/lang/Object";
  61     private static final String NAME_CTOR = "<init>";
  62     private static final String NAME_FACTORY = "get$Lambda";
  63 
  64     //Serialization support
  65     private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
  66     private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
  67     private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
  68     private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
  69     private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
  70     private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
  71     private static final String NAME_METHOD_READ_OBJECT = "readObject";
  72     private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
  73 
  74     private static final String DESCR_CLASS = "Ljava/lang/Class;";
  75     private static final String DESCR_STRING = "Ljava/lang/String;";
  76     private static final String DESCR_OBJECT = "Ljava/lang/Object;";


 284         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
 285                                           samMethodType.toMethodDescriptorString(), null, null);
 286         mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
 287         new ForwardingMethodGenerator(mv).generate(samMethodType);
 288 
 289         // Forward the bridges
 290         if (additionalBridges != null) {
 291             for (MethodType mt : additionalBridges) {
 292                 mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
 293                                     mt.toMethodDescriptorString(), null, null);
 294                 mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
 295                 new ForwardingMethodGenerator(mv).generate(mt);
 296             }
 297         }
 298 
 299         if (isSerializable)
 300             generateSerializationFriendlyMethods();
 301         else if (accidentallySerializable)
 302             generateSerializationHostileMethods();
 303 
 304         // add ValueTypes attribute
 305         Set<String> valueTypeNames = JLA.getDeclaredValueTypeNames(targetClass);
 306         if (!valueTypeNames.isEmpty()) {
 307             ValueTypesAttributeBuilder builder = new ValueTypesAttributeBuilder(valueTypeNames);
 308             builder.add(invokedType)
 309                    .add(samMethodType)
 310                    .add(implMethodType)
 311                    .add(instantiatedMethodType)
 312                    .add(additionalBridges);
 313             if (!builder.isEmpty())
 314                 cw.visitAttribute(builder.build());
 315         }
 316         cw.visitEnd();
 317 
 318         // Define the generated class in this VM.
 319 
 320         final byte[] classBytes = cw.toByteArray();
 321 
 322         // If requested, dump out to a file for debugging purposes
 323         if (dumper != null) {
 324             AccessController.doPrivileged(new PrivilegedAction<>() {
 325                 @Override
 326                 public Void run() {
 327                     dumper.dumpClass(lambdaClassName, classBytes);
 328                     return null;
 329                 }
 330             }, null,
 331             new FilePermission("<<ALL FILES>>", "read, write"),
 332             // createDirectories may need it
 333             new PropertyPermission("user.dir", "read"));
 334         }
 335 


 544             return RETURN;
 545         }
 546         return IRETURN + getOpcodeOffset(c);
 547     }
 548 
 549     private static int getOpcodeOffset(Class<?> c) {
 550         if (c.isPrimitive()) {
 551             if (c == Long.TYPE) {
 552                 return 1;
 553             } else if (c == Float.TYPE) {
 554                 return 2;
 555             } else if (c == Double.TYPE) {
 556                 return 3;
 557             }
 558             return 0;
 559         } else {
 560             return 4;
 561         }
 562     }
 563 
 564     /*
 565      * Build ValueTypes attribute
 566      */
 567     static class ValueTypesAttributeBuilder {
 568         private final Set<String> declaredValueTypes;
 569         private final Set<String> valueTypes;
 570         ValueTypesAttributeBuilder(Set<String> valueTypeNames) {
 571             this.declaredValueTypes = valueTypeNames;
 572             this.valueTypes = new HashSet<>();
 573         }
 574 
 575         /*
 576          * Add the value types referenced in the given MethodType.
 577          */
 578         ValueTypesAttributeBuilder add(MethodType mt) {
 579             // parameter types
 580             for (Class<?> paramType : mt.ptypes()) {
 581                 if (isDeclaredValueType(paramType))
 582                     valueTypes.add(paramType.getName());
 583             }
 584             // return type
 585             if (isDeclaredValueType(mt.returnType()))
 586                 valueTypes.add(mt.returnType().getName());
 587             return this;
 588         }
 589 
 590         ValueTypesAttributeBuilder add(MethodType... mtypes) {
 591             for (MethodType mt : mtypes) {
 592                 add(mt);
 593             }
 594             return this;
 595         }
 596 
 597         boolean isDeclaredValueType(Class<?> c) {
 598             while (c.isArray())
 599                 c = c.getComponentType();
 600             return declaredValueTypes.contains(c.getName());
 601         }
 602 
 603         boolean isEmpty() {
 604             return valueTypes.isEmpty();
 605         }
 606 
 607         Attribute build() {
 608             return new Attribute("ValueTypes") {
 609                 @Override
 610                 protected ByteVector write(ClassWriter cw,
 611                                            byte[] code,
 612                                            int len,
 613                                            int maxStack,
 614                                            int maxLocals) {
 615                     ByteVector attr = new ByteVector();
 616                     attr.putShort(valueTypes.size());
 617                     for (String cn : valueTypes) {
 618                         attr.putShort(cw.newClass(cn.replace('.', '/')));
 619                     }
 620                     return attr;
 621                 }
 622             };
 623         }
 624     }
 625 
 626 }
< prev index next >