mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +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
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue