mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8340131: Refactor internal makeHiddenClassDefiner to take option mask instead of Set<ClassOption>
Reviewed-by: liach, jvernee
This commit is contained in:
parent
05b9d47905
commit
e1ebeef040
6 changed files with 44 additions and 25 deletions
|
@ -53,6 +53,8 @@ import java.lang.classfile.constantpool.ClassEntry;
|
||||||
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||||
import java.lang.classfile.constantpool.MethodRefEntry;
|
import java.lang.classfile.constantpool.MethodRefEntry;
|
||||||
import static java.lang.constant.ConstantDescs.*;
|
import static java.lang.constant.ConstantDescs.*;
|
||||||
|
import static java.lang.invoke.MethodHandleNatives.Constants.NESTMATE_CLASS;
|
||||||
|
import static java.lang.invoke.MethodHandleNatives.Constants.STRONG_LOADER_LINK;
|
||||||
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
|
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
|
||||||
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
|
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
|
||||||
import static java.lang.invoke.MethodType.methodType;
|
import static java.lang.invoke.MethodType.methodType;
|
||||||
|
@ -348,7 +350,7 @@ import sun.invoke.util.Wrapper;
|
||||||
try {
|
try {
|
||||||
// this class is linked at the indy callsite; so define a hidden nestmate
|
// this class is linked at the indy callsite; so define a hidden nestmate
|
||||||
var classdata = useImplMethodHandle? implementation : null;
|
var classdata = useImplMethodHandle? implementation : null;
|
||||||
return caller.makeHiddenClassDefiner(lambdaClassName, classBytes, Set.of(NESTMATE, STRONG), lambdaProxyClassFileDumper)
|
return caller.makeHiddenClassDefiner(lambdaClassName, classBytes, lambdaProxyClassFileDumper, NESTMATE_CLASS | STRONG_LOADER_LINK)
|
||||||
.defineClass(!disableEagerInitialization, classdata);
|
.defineClass(!disableEagerInitialization, classdata);
|
||||||
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
|
|
@ -47,7 +47,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import jdk.internal.constant.MethodTypeDescImpl;
|
import jdk.internal.constant.MethodTypeDescImpl;
|
||||||
|
@ -224,7 +223,7 @@ class InvokerBytecodeGenerator {
|
||||||
* Extract the MemberName of a newly-defined method.
|
* Extract the MemberName of a newly-defined method.
|
||||||
*/
|
*/
|
||||||
private MemberName loadMethod(byte[] classFile) {
|
private MemberName loadMethod(byte[] classFile) {
|
||||||
Class<?> invokerClass = LOOKUP.makeHiddenClassDefiner(className, classFile, Set.of(), dumper())
|
Class<?> invokerClass = LOOKUP.makeHiddenClassDefiner(className, classFile, dumper())
|
||||||
.defineClass(true, classDataValues());
|
.defineClass(true, classDataValues());
|
||||||
return resolveInvokerMember(invokerClass, invokerName, invokerType);
|
return resolveInvokerMember(invokerClass, invokerName, invokerType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ import static java.lang.constant.ConstantDescs.*;
|
||||||
import static java.lang.invoke.LambdaForm.*;
|
import static java.lang.invoke.LambdaForm.*;
|
||||||
import static java.lang.invoke.MethodHandleNatives.Constants.MN_CALLER_SENSITIVE;
|
import static java.lang.invoke.MethodHandleNatives.Constants.MN_CALLER_SENSITIVE;
|
||||||
import static java.lang.invoke.MethodHandleNatives.Constants.MN_HIDDEN_MEMBER;
|
import static java.lang.invoke.MethodHandleNatives.Constants.MN_HIDDEN_MEMBER;
|
||||||
|
import static java.lang.invoke.MethodHandleNatives.Constants.NESTMATE_CLASS;
|
||||||
import static java.lang.invoke.MethodHandleStatics.*;
|
import static java.lang.invoke.MethodHandleStatics.*;
|
||||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||||
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
|
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
|
||||||
|
@ -1111,7 +1112,7 @@ abstract class MethodHandleImpl {
|
||||||
}
|
}
|
||||||
name = name.replace('.', '/');
|
name = name.replace('.', '/');
|
||||||
Class<?> invokerClass = new Lookup(targetClass)
|
Class<?> invokerClass = new Lookup(targetClass)
|
||||||
.makeHiddenClassDefiner(name, INJECTED_INVOKER_TEMPLATE, Set.of(NESTMATE), dumper())
|
.makeHiddenClassDefiner(name, INJECTED_INVOKER_TEMPLATE, dumper(), NESTMATE_CLASS)
|
||||||
.defineClass(true, targetClass);
|
.defineClass(true, targetClass);
|
||||||
assert checkInjectedInvoker(targetClass, invokerClass);
|
assert checkInjectedInvoker(targetClass, invokerClass);
|
||||||
return invokerClass;
|
return invokerClass;
|
||||||
|
|
|
@ -285,7 +285,7 @@ public class MethodHandleProxies {
|
||||||
byte[] template = createTemplate(loader, binaryNameToDesc(className),
|
byte[] template = createTemplate(loader, binaryNameToDesc(className),
|
||||||
referenceClassDesc(intfc), uniqueName, methods);
|
referenceClassDesc(intfc), uniqueName, methods);
|
||||||
// define the dynamic module to the class loader of the interface
|
// define the dynamic module to the class loader of the interface
|
||||||
var definer = new Lookup(intfc).makeHiddenClassDefiner(className, template, Set.of(), DUMPER);
|
var definer = new Lookup(intfc).makeHiddenClassDefiner(className, template, DUMPER);
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
var sm = System.getSecurityManager();
|
var sm = System.getSecurityManager();
|
||||||
|
|
|
@ -1906,9 +1906,12 @@ public class MethodHandles {
|
||||||
this.flag = flag;
|
this.flag = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int optionsToFlag(Set<ClassOption> options) {
|
static int optionsToFlag(ClassOption[] options) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
for (ClassOption cp : options) {
|
for (ClassOption cp : options) {
|
||||||
|
if ((flags & cp.flag) != 0) {
|
||||||
|
throw new IllegalArgumentException("Duplicate ClassOption " + cp);
|
||||||
|
}
|
||||||
flags |= cp.flag;
|
flags |= cp.flag;
|
||||||
}
|
}
|
||||||
return flags;
|
return flags;
|
||||||
|
@ -2126,14 +2129,13 @@ public class MethodHandles {
|
||||||
throws IllegalAccessException
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
Objects.requireNonNull(bytes);
|
Objects.requireNonNull(bytes);
|
||||||
Objects.requireNonNull(options);
|
int flags = ClassOption.optionsToFlag(options);
|
||||||
|
|
||||||
ensureDefineClassPermission();
|
ensureDefineClassPermission();
|
||||||
if (!hasFullPrivilegeAccess()) {
|
if (!hasFullPrivilegeAccess()) {
|
||||||
throw new IllegalAccessException(this + " does not have full privilege access");
|
throw new IllegalAccessException(this + " does not have full privilege access");
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeHiddenClassDefiner(bytes.clone(), Set.of(options), false).defineClassAsLookup(initialize);
|
return makeHiddenClassDefiner(bytes.clone(), false, flags).defineClassAsLookup(initialize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2213,14 +2215,15 @@ public class MethodHandles {
|
||||||
{
|
{
|
||||||
Objects.requireNonNull(bytes);
|
Objects.requireNonNull(bytes);
|
||||||
Objects.requireNonNull(classData);
|
Objects.requireNonNull(classData);
|
||||||
Objects.requireNonNull(options);
|
|
||||||
|
int flags = ClassOption.optionsToFlag(options);
|
||||||
|
|
||||||
ensureDefineClassPermission();
|
ensureDefineClassPermission();
|
||||||
if (!hasFullPrivilegeAccess()) {
|
if (!hasFullPrivilegeAccess()) {
|
||||||
throw new IllegalAccessException(this + " does not have full privilege access");
|
throw new IllegalAccessException(this + " does not have full privilege access");
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeHiddenClassDefiner(bytes.clone(), Set.of(options), false)
|
return makeHiddenClassDefiner(bytes.clone(), false, flags)
|
||||||
.defineClassAsLookup(initialize, classData);
|
.defineClassAsLookup(initialize, classData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2366,7 +2369,7 @@ public class MethodHandles {
|
||||||
*/
|
*/
|
||||||
ClassDefiner makeHiddenClassDefiner(byte[] bytes, ClassFileDumper dumper) {
|
ClassDefiner makeHiddenClassDefiner(byte[] bytes, ClassFileDumper dumper) {
|
||||||
ClassFile cf = ClassFile.newInstance(bytes, lookupClass().getPackageName());
|
ClassFile cf = ClassFile.newInstance(bytes, lookupClass().getPackageName());
|
||||||
return makeHiddenClassDefiner(cf, Set.of(), false, dumper);
|
return makeHiddenClassDefiner(cf, false, dumper, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2378,7 +2381,7 @@ public class MethodHandles {
|
||||||
* before calling this factory method.
|
* before calling this factory method.
|
||||||
*
|
*
|
||||||
* @param bytes class bytes
|
* @param bytes class bytes
|
||||||
* @param options class options
|
* @param flags class option flag mask
|
||||||
* @param accessVmAnnotations true to give the hidden class access to VM annotations
|
* @param accessVmAnnotations true to give the hidden class access to VM annotations
|
||||||
* @return ClassDefiner that defines a hidden class of the given bytes and options
|
* @return ClassDefiner that defines a hidden class of the given bytes and options
|
||||||
*
|
*
|
||||||
|
@ -2386,10 +2389,10 @@ public class MethodHandles {
|
||||||
* {@code bytes} denotes a class in a different package than the lookup class
|
* {@code bytes} denotes a class in a different package than the lookup class
|
||||||
*/
|
*/
|
||||||
private ClassDefiner makeHiddenClassDefiner(byte[] bytes,
|
private ClassDefiner makeHiddenClassDefiner(byte[] bytes,
|
||||||
Set<ClassOption> options,
|
boolean accessVmAnnotations,
|
||||||
boolean accessVmAnnotations) {
|
int flags) {
|
||||||
ClassFile cf = ClassFile.newInstance(bytes, lookupClass().getPackageName());
|
ClassFile cf = ClassFile.newInstance(bytes, lookupClass().getPackageName());
|
||||||
return makeHiddenClassDefiner(cf, options, accessVmAnnotations, defaultDumper());
|
return makeHiddenClassDefiner(cf, accessVmAnnotations, defaultDumper(), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2398,14 +2401,29 @@ public class MethodHandles {
|
||||||
*
|
*
|
||||||
* @param name internal name that specifies the prefix of the hidden class
|
* @param name internal name that specifies the prefix of the hidden class
|
||||||
* @param bytes class bytes
|
* @param bytes class bytes
|
||||||
* @param options class options
|
|
||||||
* @param dumper dumper to write the given bytes to the dumper's output directory
|
* @param dumper dumper to write the given bytes to the dumper's output directory
|
||||||
* @return ClassDefiner that defines a hidden class of the given bytes and options.
|
* @return ClassDefiner that defines a hidden class of the given bytes and options.
|
||||||
*/
|
*/
|
||||||
ClassDefiner makeHiddenClassDefiner(String name, byte[] bytes, Set<ClassOption> options, ClassFileDumper dumper) {
|
ClassDefiner makeHiddenClassDefiner(String name, byte[] bytes, ClassFileDumper dumper) {
|
||||||
Objects.requireNonNull(dumper);
|
Objects.requireNonNull(dumper);
|
||||||
// skip name and access flags validation
|
// skip name and access flags validation
|
||||||
return makeHiddenClassDefiner(ClassFile.newInstanceNoCheck(name, bytes), options, false, dumper);
|
return makeHiddenClassDefiner(ClassFile.newInstanceNoCheck(name, bytes), false, dumper, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a ClassDefiner that creates a {@code Class} object of a hidden class
|
||||||
|
* from the given bytes and the given options. No package name check on the given bytes.
|
||||||
|
*
|
||||||
|
* @param name internal name that specifies the prefix of the hidden class
|
||||||
|
* @param bytes class bytes
|
||||||
|
* @param flags class options flag mask
|
||||||
|
* @param dumper dumper to write the given bytes to the dumper's output directory
|
||||||
|
* @return ClassDefiner that defines a hidden class of the given bytes and options.
|
||||||
|
*/
|
||||||
|
ClassDefiner makeHiddenClassDefiner(String name, byte[] bytes, ClassFileDumper dumper, int flags) {
|
||||||
|
Objects.requireNonNull(dumper);
|
||||||
|
// skip name and access flags validation
|
||||||
|
return makeHiddenClassDefiner(ClassFile.newInstanceNoCheck(name, bytes), false, dumper, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2413,15 +2431,15 @@ public class MethodHandles {
|
||||||
* from the given class file and options.
|
* from the given class file and options.
|
||||||
*
|
*
|
||||||
* @param cf ClassFile
|
* @param cf ClassFile
|
||||||
* @param options class options
|
* @param flags class option flag mask
|
||||||
* @param accessVmAnnotations true to give the hidden class access to VM annotations
|
* @param accessVmAnnotations true to give the hidden class access to VM annotations
|
||||||
* @param dumper dumper to write the given bytes to the dumper's output directory
|
* @param dumper dumper to write the given bytes to the dumper's output directory
|
||||||
*/
|
*/
|
||||||
private ClassDefiner makeHiddenClassDefiner(ClassFile cf,
|
private ClassDefiner makeHiddenClassDefiner(ClassFile cf,
|
||||||
Set<ClassOption> options,
|
|
||||||
boolean accessVmAnnotations,
|
boolean accessVmAnnotations,
|
||||||
ClassFileDumper dumper) {
|
ClassFileDumper dumper,
|
||||||
int flags = HIDDEN_CLASS | ClassOption.optionsToFlag(options);
|
int flags) {
|
||||||
|
flags |= HIDDEN_CLASS;
|
||||||
if (accessVmAnnotations | VM.isSystemDomainLoader(lookupClass.getClassLoader())) {
|
if (accessVmAnnotations | VM.isSystemDomainLoader(lookupClass.getClassLoader())) {
|
||||||
// jdk.internal.vm.annotations are permitted for classes
|
// jdk.internal.vm.annotations are permitted for classes
|
||||||
// defined to boot loader and platform loader
|
// defined to boot loader and platform loader
|
||||||
|
|
|
@ -51,7 +51,6 @@ import java.lang.invoke.MethodHandles.Lookup;
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
@ -1353,7 +1352,7 @@ public final class StringConcatFactory {
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
try {
|
try {
|
||||||
var hiddenClass = lookup.makeHiddenClassDefiner(CLASS_NAME, classBytes, Set.of(), DUMPER)
|
var hiddenClass = lookup.makeHiddenClassDefiner(CLASS_NAME, classBytes, DUMPER)
|
||||||
.defineClass(true, null);
|
.defineClass(true, null);
|
||||||
|
|
||||||
if (staticConcat) {
|
if (staticConcat) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue