8304846: Provide a shared utility to dump generated classes defined via Lookup API

Reviewed-by: jvernee
This commit is contained in:
Mandy Chung 2023-04-04 18:07:02 +00:00
parent 2ee4245105
commit dd59471798
11 changed files with 440 additions and 393 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2023, 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
@ -34,11 +34,7 @@ import jdk.internal.org.objectweb.asm.Type;
import sun.invoke.util.VerifyAccess;
import sun.invoke.util.VerifyType;
import sun.invoke.util.Wrapper;
import sun.reflect.misc.ReflectUtil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
@ -125,7 +121,7 @@ class InvokerBytecodeGenerator {
name = invokerName.substring(0, p);
invokerName = invokerName.substring(p + 1);
}
if (DUMP_CLASS_FILES) {
if (dumper().isEnabled()) {
name = makeDumpableClassName(name);
}
this.name = name;
@ -173,58 +169,8 @@ class InvokerBytecodeGenerator {
}
/** instance counters for dumped classes */
private static final HashMap<String,Integer> DUMP_CLASS_FILES_COUNTERS;
/** debugging flag for saving generated class files */
private static final File DUMP_CLASS_FILES_DIR;
static {
if (DUMP_CLASS_FILES) {
DUMP_CLASS_FILES_COUNTERS = new HashMap<>();
try {
File dumpDir = new File("DUMP_CLASS_FILES");
if (!dumpDir.exists()) {
dumpDir.mkdirs();
}
DUMP_CLASS_FILES_DIR = dumpDir;
System.out.println("Dumping class files to "+DUMP_CLASS_FILES_DIR+"/...");
} catch (Exception e) {
throw newInternalError(e);
}
} else {
DUMP_CLASS_FILES_COUNTERS = null;
DUMP_CLASS_FILES_DIR = null;
}
}
private void maybeDump(final byte[] classFile) {
if (DUMP_CLASS_FILES) {
maybeDump(className, classFile);
}
}
// Also used from BoundMethodHandle
@SuppressWarnings("removal")
static void maybeDump(final String className, final byte[] classFile) {
if (DUMP_CLASS_FILES) {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
try {
String dumpName = className.replace('.','/');
File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class");
System.out.println("dump: " + dumpFile);
dumpFile.getParentFile().mkdirs();
FileOutputStream file = new FileOutputStream(dumpFile);
file.write(classFile);
file.close();
return null;
} catch (IOException ex) {
throw newInternalError(ex);
}
}
});
}
}
private static final HashMap<String,Integer> DUMP_CLASS_FILES_COUNTERS =
dumper().isEnabled() ? new HashMap<>(): null;
private static String makeDumpableClassName(String className) {
Integer ctr;
@ -271,7 +217,7 @@ class InvokerBytecodeGenerator {
// unique static variable name
String name;
if (DUMP_CLASS_FILES) {
if (dumper().isEnabled()) {
Class<?> c = arg.getClass();
while (c.isArray()) {
c = c.getComponentType();
@ -299,7 +245,7 @@ class InvokerBytecodeGenerator {
* Extract the MemberName of a newly-defined method.
*/
private MemberName loadMethod(byte[] classFile) {
Class<?> invokerClass = LOOKUP.makeHiddenClassDefiner(className, classFile, Set.of())
Class<?> invokerClass = LOOKUP.makeHiddenClassDefiner(className, classFile, Set.of(), dumper())
.defineClass(true, classDataValues());
return resolveInvokerMember(invokerClass, invokerName, invokerType);
}
@ -809,9 +755,7 @@ class InvokerBytecodeGenerator {
clinit(cw, className, classData);
bogusMethod(lambdaForm);
final byte[] classFile = toByteArray();
maybeDump(classFile);
return classFile;
return toByteArray();
}
void setClassWriter(ClassWriter cw) {
@ -1898,9 +1842,7 @@ class InvokerBytecodeGenerator {
clinit(cw, className, classData);
bogusMethod(invokerType);
final byte[] classFile = cw.toByteArray();
maybeDump(classFile);
return classFile;
return cw.toByteArray();
}
/**
@ -1967,9 +1909,7 @@ class InvokerBytecodeGenerator {
clinit(cw, className, classData);
bogusMethod(dstType);
final byte[] classFile = cw.toByteArray();
maybeDump(classFile);
return classFile;
return cw.toByteArray();
}
/**
@ -1977,7 +1917,7 @@ class InvokerBytecodeGenerator {
* for debugging purposes.
*/
private void bogusMethod(Object os) {
if (DUMP_CLASS_FILES) {
if (dumper().isEnabled()) {
mv = cw.visitMethod(Opcodes.ACC_STATIC, "dummy", "()V", null, null);
mv.visitLdcInsn(os.toString());
mv.visitInsn(Opcodes.POP);