8294960: Convert java.base/java.lang.invoke package to use the Classfile API to generate lambdas and method handles

Co-authored-by: Claes Redestad <redestad@openjdk.org>
Reviewed-by: redestad, liach
This commit is contained in:
Adam Sotona 2024-06-19 15:15:30 +00:00
parent 50bed6c67b
commit 01ee4241b7
11 changed files with 1286 additions and 1704 deletions

View file

@ -28,9 +28,6 @@ package java.lang.invoke;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.CallerSensitiveAdapter;
import jdk.internal.reflect.Reflection;
@ -42,8 +39,10 @@ import sun.invoke.util.Wrapper;
import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants;
import java.lang.classfile.ClassModel;
import java.lang.constant.ConstantDescs;
import java.lang.invoke.LambdaForm.BasicType;
import java.lang.invoke.MethodHandleImpl.Intrinsic;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
@ -62,8 +61,8 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import static java.lang.classfile.ClassFile.*;
import static java.lang.invoke.LambdaForm.BasicType.V_TYPE;
import static java.lang.invoke.MethodHandleImpl.Intrinsic;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
@ -2288,27 +2287,16 @@ public class MethodHandles {
String name;
int accessFlags;
try {
ClassReader reader = new ClassReader(bytes);
// ClassReader does not check if `this_class` is CONSTANT_Class_info
// workaround to read `this_class` using readConst and validate the value
int thisClass = reader.readUnsignedShort(reader.header + 2);
Object constant = reader.readConst(thisClass, new char[reader.getMaxStringLength()]);
if (!(constant instanceof Type type)) {
throw new ClassFormatError("this_class item: #" + thisClass + " not a CONSTANT_Class_info");
}
if (!type.getDescriptor().startsWith("L")) {
throw new ClassFormatError("this_class item: #" + thisClass + " not a CONSTANT_Class_info");
}
name = type.getInternalName();
accessFlags = reader.readUnsignedShort(reader.header);
} catch (RuntimeException e) {
// ASM exceptions are poorly specified
ClassModel cm = java.lang.classfile.ClassFile.of().parse(bytes);
name = cm.thisClass().asInternalName();
accessFlags = cm.flags().flagsMask();
} catch (IllegalArgumentException e) {
ClassFormatError cfe = new ClassFormatError();
cfe.initCause(e);
throw cfe;
}
// must be a class or interface
if ((accessFlags & Opcodes.ACC_MODULE) != 0) {
if ((accessFlags & ACC_MODULE) != 0) {
throw newIllegalArgumentException("Not a class or interface: ACC_MODULE flag is set");
}
return new ClassFile(name, accessFlags, bytes);