< prev index next > src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
Print this page
/*
! * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
/*
! * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* questions.
*/
package java.lang.invoke;
+ import jdk.internal.misc.PreviewFeatures;
import jdk.internal.misc.CDS;
import jdk.internal.org.objectweb.asm.*;
import sun.invoke.util.BytecodeDescriptor;
import sun.invoke.util.VerifyAccess;
import sun.security.action.GetPropertyAction;
import java.lang.constant.ConstantDescs;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
+ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.PropertyPermission;
import java.util.Set;
accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(i);
}
interfaceNames = itfs.toArray(new String[itfs.size()]);
}
! cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
lambdaClassName, null,
JAVA_LANG_OBJECT, interfaceNames);
// Generate final fields to be filled in by constructor
for (int i = 0; i < argDescs.length; i++) {
accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(i);
}
interfaceNames = itfs.toArray(new String[itfs.size()]);
}
! int version = CLASSFILE_VERSION | (PreviewFeatures.isEnabled() ? Opcodes.V_PREVIEW : 0);
+ cw.visit(version, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
lambdaClassName, null,
JAVA_LANG_OBJECT, interfaceNames);
// Generate final fields to be filled in by constructor
for (int i = 0; i < argDescs.length; i++) {
if (isSerializable)
generateSerializationFriendlyMethods();
else if (accidentallySerializable)
generateSerializationHostileMethods();
+ // generate Preload attribute if it references any value class
+ PreloadAttributeBuilder builder = new PreloadAttributeBuilder(targetClass);
+ builder.add(factoryType)
+ .add(interfaceMethodType)
+ .add(implMethodType)
+ .add(dynamicMethodType)
+ .add(altMethods);
+ if (!builder.isEmpty())
+ cw.visitAttribute(builder.build());
+
cw.visitEnd();
// Define the generated class in this VM.
final byte[] classBytes = cw.toByteArray();
default -> throw new InternalError("Unexpected invocation kind: " + implKind);
};
}
}
+ /*
+ * Preload attribute builder
+ */
+ static class PreloadAttributeBuilder {
+ private final Set<Class<?>> preloadClasses = new HashSet<>();
+ PreloadAttributeBuilder(Class<?> targetClass) {
+ if (requiresPreload(targetClass)) {
+ preloadClasses.add(targetClass);
+ }
+ }
+
+ /*
+ * Add the value types referenced in the given MethodType.
+ */
+ PreloadAttributeBuilder add(MethodType mt) {
+ // parameter types
+ for (Class<?> paramType : mt.ptypes()) {
+ if (requiresPreload(paramType)) {
+ preloadClasses.add(paramType);
+ }
+ }
+ // return type
+ if (requiresPreload(mt.returnType())) {
+ preloadClasses.add(mt.returnType());
+ }
+ return this;
+ }
+
+ PreloadAttributeBuilder add(MethodType... mtypes) {
+ for (MethodType mt : mtypes) {
+ add(mt);
+ }
+ return this;
+ }
+
+ boolean requiresPreload(Class<?> cls) {
+ Class<?> c = cls;
+ while (c.isArray()) {
+ c = c.getComponentType();
+ }
+ return c.isValue();
+ }
+
+ boolean isEmpty() {
+ return preloadClasses.isEmpty();
+ }
+
+ Attribute build() {
+ return new Attribute("Preload") {
+ @Override
+ protected ByteVector write(ClassWriter cw,
+ byte[] code,
+ int len,
+ int maxStack,
+ int maxLocals) {
+ ByteVector attr = new ByteVector();
+ attr.putShort(preloadClasses.size());
+ for (Class<?> c : preloadClasses) {
+ attr.putShort(cw.newClass(Type.getInternalName(c)));
+ }
+ return attr;
+ }
+ };
+ }
+ }
+
static int getParameterSize(Class<?> c) {
if (c == Void.TYPE) {
return 0;
} else if (c == Long.TYPE || c == Double.TYPE) {
return 2;
< prev index next >