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 } |