mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8304846: Provide a shared utility to dump generated classes defined via Lookup API
Reviewed-by: jvernee
This commit is contained in:
parent
2ee4245105
commit
dd59471798
11 changed files with 440 additions and 393 deletions
|
@ -27,21 +27,16 @@ package java.lang.invoke;
|
|||
|
||||
import jdk.internal.misc.CDS;
|
||||
import jdk.internal.org.objectweb.asm.*;
|
||||
import jdk.internal.util.ClassFileDumper;
|
||||
import sun.invoke.util.BytecodeDescriptor;
|
||||
import sun.invoke.util.VerifyAccess;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.security.action.GetBooleanAction;
|
||||
|
||||
import java.io.FilePermission;
|
||||
import java.io.Serializable;
|
||||
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.nio.file.Path;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.PropertyPermission;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.CLASSFILE_VERSION;
|
||||
|
@ -85,11 +80,8 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
// Used to ensure that dumped class files for failed definitions have a unique class name
|
||||
private static final AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
// For dumping generated classes to disk, for debugging purposes
|
||||
private static final ProxyClassesDumper dumper;
|
||||
private static final ClassFileDumper lambdaProxyClassFileDumper;
|
||||
|
||||
private static final boolean disableEagerInitialization;
|
||||
|
||||
|
@ -97,9 +89,11 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
private static final ConstantDynamic implMethodCondy;
|
||||
|
||||
static {
|
||||
final String dumpProxyClassesKey = "jdk.internal.lambda.dumpProxyClasses";
|
||||
String dumpPath = GetPropertyAction.privilegedGetProperty(dumpProxyClassesKey);
|
||||
dumper = (null == dumpPath) ? null : ProxyClassesDumper.getInstance(dumpPath);
|
||||
// To dump the lambda proxy classes, set this system property:
|
||||
// -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles
|
||||
// or -Djdk.invoke.LambdaMetafactory.dumpProxyClassFiles=true
|
||||
final String dumpProxyClassesKey = "jdk.invoke.LambdaMetafactory.dumpProxyClassFiles";
|
||||
lambdaProxyClassFileDumper = ClassFileDumper.getInstance(dumpProxyClassesKey, Path.of("DUMP_LAMBDA_PROXY_CLASS_FILES"));
|
||||
|
||||
final String disableEagerInitializationKey = "jdk.internal.lambda.disableEagerInitialization";
|
||||
disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey);
|
||||
|
@ -363,51 +357,15 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
final byte[] classBytes = cw.toByteArray();
|
||||
try {
|
||||
// this class is linked at the indy callsite; so define a hidden nestmate
|
||||
Lookup lookup = null;
|
||||
try {
|
||||
if (useImplMethodHandle) {
|
||||
lookup = caller.defineHiddenClassWithClassData(classBytes, implementation, !disableEagerInitialization,
|
||||
NESTMATE, STRONG);
|
||||
} else {
|
||||
lookup = caller.defineHiddenClass(classBytes, !disableEagerInitialization, NESTMATE, STRONG);
|
||||
}
|
||||
return lookup.lookupClass();
|
||||
} finally {
|
||||
// If requested, dump out to a file for debugging purposes
|
||||
if (dumper != null) {
|
||||
String name;
|
||||
if (lookup != null) {
|
||||
String definedName = lookup.lookupClass().getName();
|
||||
int suffixIdx = definedName.lastIndexOf('/');
|
||||
assert suffixIdx != -1;
|
||||
name = lambdaClassName + '.' + definedName.substring(suffixIdx + 1);
|
||||
} else {
|
||||
name = lambdaClassName + ".failed-" + counter.incrementAndGet();
|
||||
}
|
||||
doDump(name, classBytes);
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new LambdaConversionException("Exception defining lambda proxy class", e);
|
||||
var classdata = useImplMethodHandle? implementation : null;
|
||||
return caller.makeHiddenClassDefiner(lambdaClassName, classBytes, Set.of(NESTMATE, STRONG), lambdaProxyClassFileDumper)
|
||||
.defineClass(!disableEagerInitialization, classdata);
|
||||
|
||||
} catch (Throwable t) {
|
||||
throw new InternalError(t);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void doDump(final String className, final byte[] classBytes) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
dumper.dumpClass(className, classBytes);
|
||||
return null;
|
||||
}
|
||||
}, null,
|
||||
new FilePermission("<<ALL FILES>>", "read, write"),
|
||||
// createDirectories may need it
|
||||
new PropertyPermission("user.dir", "read"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a static field and a static initializer that sets this field to an instance of the lambda
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue