8294969: Convert jdk.jdeps javap to use the Classfile API

Reviewed-by: vromero
This commit is contained in:
Adam Sotona 2023-09-18 08:35:31 +00:00
parent fbc766ee21
commit 1203e11a8d
29 changed files with 2012 additions and 2870 deletions

View file

@ -67,7 +67,10 @@ import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import com.sun.tools.classfile.*;
import jdk.internal.classfile.ClassModel;
import jdk.internal.classfile.Classfile;
import jdk.internal.classfile.constantpool.*;
import static jdk.internal.classfile.Classfile.*;
/**
* "Main" class for javap, normally accessed from the command line
@ -166,7 +169,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
@Override
void process(JavapTask task, String opt, String arg) {
task.options.accessOptions.add(opt);
task.options.showAccess = AccessFlags.ACC_PUBLIC;
task.options.showAccess = ACC_PUBLIC;
}
},
@ -174,7 +177,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
@Override
void process(JavapTask task, String opt, String arg) {
task.options.accessOptions.add(opt);
task.options.showAccess = AccessFlags.ACC_PROTECTED;
task.options.showAccess = ACC_PROTECTED;
}
},
@ -193,7 +196,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
!task.options.accessOptions.contains("-private")) {
task.options.accessOptions.add(opt);
}
task.options.showAccess = AccessFlags.ACC_PRIVATE;
task.options.showAccess = ACC_PRIVATE;
}
},
@ -349,7 +352,6 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
context = new Context();
context.put(Messages.class, this);
options = Options.instance(context);
attributeFactory = new Attribute.Factory();
}
public JavapTask(Writer out,
@ -633,7 +635,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
} catch (OutOfMemoryError e) {
reportError("err.nomem");
result = EXIT_ERROR;
} catch (FatalError e) {
} catch (IllegalArgumentException e) {
Object msg = e.getLocalizedMessage();
if (msg == null) {
msg = e;
@ -654,7 +656,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
}
protected int writeClass(ClassWriter classWriter, String className)
throws IOException, ConstantPoolException {
throws IOException {
JavaFileObject fo = open(className);
if (fo == null) {
reportError("err.class.not.found", className);
@ -663,34 +665,26 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
ClassFileInfo cfInfo = read(fo);
if (!className.endsWith(".class")) {
if (cfInfo.cf.this_class == 0) {
if (!className.equals("module-info")) {
reportWarning("warn.unexpected.class", fo.getName(), className);
}
} else {
String cfName = cfInfo.cf.getName();
if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", "."))) {
reportWarning("warn.unexpected.class", fo.getName(), className);
}
String cfName = cfInfo.cm.thisClass().asInternalName();
if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", "."))) {
reportWarning("warn.unexpected.class", fo.getName(), className);
}
}
write(cfInfo);
if (!write(cfInfo)) return EXIT_ERROR;
if (options.showInnerClasses) {
ClassFile cf = cfInfo.cf;
Attribute a = cf.getAttribute(Attribute.InnerClasses);
if (a instanceof InnerClasses_attribute) {
InnerClasses_attribute inners = (InnerClasses_attribute) a;
ClassModel cm = cfInfo.cm;
var a = cm.findAttribute(jdk.internal.classfile.Attributes.INNER_CLASSES);
if (a.isPresent()) {
var inners = a.get();
try {
int result = EXIT_OK;
for (int i = 0; i < inners.classes.length; i++) {
int outerIndex = inners.classes[i].outer_class_info_index;
ConstantPool.CONSTANT_Class_info outerClassInfo = cf.constant_pool.getClassInfo(outerIndex);
String outerClassName = outerClassInfo.getName();
if (outerClassName.equals(cf.getName())) {
int innerIndex = inners.classes[i].inner_class_info_index;
ConstantPool.CONSTANT_Class_info innerClassInfo = cf.constant_pool.getClassInfo(innerIndex);
String innerClassName = innerClassInfo.getName();
for (var inner : inners.classes()) {
var outerClassInfo = inner.outerClass();
String outerClassName = outerClassInfo.map(ClassEntry::asInternalName).orElse(null);
if (cm.thisClass().asInternalName().equals(outerClassName)) {
var innerClassInfo = inner.innerClass();
String innerClassName = innerClassInfo.asInternalName();
classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", "."));
classWriter.println();
result = writeClass(classWriter, innerClassName);
@ -698,13 +692,10 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
}
}
return result;
} catch (ConstantPoolException e) {
} catch (IllegalArgumentException e) {
reportError("err.bad.innerclasses.attribute", className);
return EXIT_ERROR;
}
} else if (a != null) {
reportError("err.bad.innerclasses.attribute", className);
return EXIT_ERROR;
}
}
@ -811,19 +802,19 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
}
public static class ClassFileInfo {
ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {
ClassFileInfo(JavaFileObject fo, ClassModel cm, byte[] digest, int size) {
this.fo = fo;
this.cf = cf;
this.cm = cm;
this.digest = digest;
this.size = size;
}
public final JavaFileObject fo;
public final ClassFile cf;
public final ClassModel cm;
public final byte[] digest;
public final int size;
}
public ClassFileInfo read(JavaFileObject fo) throws IOException, ConstantPoolException {
public ClassFileInfo read(JavaFileObject fo) throws IOException {
InputStream in = fo.openInputStream();
try {
SizeInputStream sizeIn = null;
@ -836,17 +827,16 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
in = new DigestInputStream(in, md);
in = sizeIn = new SizeInputStream(in);
}
ClassFile cf = ClassFile.read(in, attributeFactory);
ClassModel cm = Classfile.of().parse(in.readAllBytes());
byte[] digest = (md == null) ? null : md.digest();
int size = (sizeIn == null) ? -1 : sizeIn.size();
return new ClassFileInfo(fo, cf, digest, size);
return new ClassFileInfo(fo, cm, digest, size);
} finally {
in.close();
}
}
public void write(ClassFileInfo info) {
public boolean write(ClassFileInfo info) {
ClassWriter classWriter = ClassWriter.instance(context);
if (options.sysInfo || options.verbose) {
classWriter.setFile(info.fo.toUri());
@ -855,56 +845,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
classWriter.setFileSize(info.size);
}
classWriter.write(info.cf);
}
protected void setClassFile(ClassFile classFile) {
ClassWriter classWriter = ClassWriter.instance(context);
classWriter.setClassFile(classFile);
}
protected void setMethod(Method enclosingMethod) {
ClassWriter classWriter = ClassWriter.instance(context);
classWriter.setMethod(enclosingMethod);
}
protected void write(Attribute value) {
AttributeWriter attrWriter = AttributeWriter.instance(context);
ClassWriter classWriter = ClassWriter.instance(context);
ClassFile cf = classWriter.getClassFile();
attrWriter.write(cf, value, cf.constant_pool);
}
protected void write(Attributes attrs) {
AttributeWriter attrWriter = AttributeWriter.instance(context);
ClassWriter classWriter = ClassWriter.instance(context);
ClassFile cf = classWriter.getClassFile();
attrWriter.write(cf, attrs, cf.constant_pool);
}
protected void write(ConstantPool constant_pool) {
ConstantWriter constantWriter = ConstantWriter.instance(context);
constantWriter.writeConstantPool(constant_pool);
}
protected void write(ConstantPool constant_pool, int value) {
ConstantWriter constantWriter = ConstantWriter.instance(context);
constantWriter.write(value);
}
protected void write(ConstantPool.CPInfo value) {
ConstantWriter constantWriter = ConstantWriter.instance(context);
constantWriter.println(value);
}
protected void write(Field value) {
ClassWriter classWriter = ClassWriter.instance(context);
classWriter.writeField(value);
}
protected void write(Method value) {
ClassWriter classWriter = ClassWriter.instance(context);
classWriter.writeMethod(value);
return classWriter.write(info.cm);
}
private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
@ -944,7 +885,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
if (result == null)
result = l;
else
throw new IOException("multiple definitions found for " + moduleName);
throw new IOException("multiple definitions found for "
+ moduleName);
}
}
if (result != null)
@ -957,7 +899,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
private void showHelp() {
printLines(getMessage("main.usage", progname));
for (Option o: recognizedOptions) {
String name = o.aliases[0].replaceAll("^-+", "").replaceAll("-+", "_"); // there must always be at least one name
// there must always be at least one name
String name = o.aliases[0].replaceAll("^-+", "").replaceAll("-+", "_");
if (name.startsWith("X") || name.equals("fullversion"))
continue;
printLines(getMessage("main.opt." + name));
@ -1000,7 +943,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
try {
versionRB = ResourceBundle.getBundle(versionRBName);
} catch (MissingResourceException e) {
return getMessage("version.resource.missing", System.getProperty("java.version"));
return getMessage("version.resource.missing",
System.getProperty("java.version"));
}
}
try {
@ -1064,7 +1008,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
@Override
public String toString() {
return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]";
return getClass().getName() + "[key=" + key + ",args="
+ Arrays.asList(args) + "]";
}
};
@ -1089,10 +1034,12 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
ResourceBundle b = bundles.get(locale);
if (b == null) {
try {
b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", locale);
b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap",
locale);
bundles.put(locale, b);
} catch (MissingResourceException e) {
throw new InternalError("Cannot find javap resource bundle for locale " + locale);
throw new InternalError("Cannot find javap resource bundle for locale "
+ locale);
}
}
@ -1114,7 +1061,6 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
//ResourceBundle bundle;
Locale task_locale;
Map<Locale, ResourceBundle> bundles;
protected Attribute.Factory attributeFactory;
private static final String progname = "javap";