mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-01 22:18:23 +00:00
4880672: javap does not output inner interfaces of an interface
Reviewed-by: mcimadamore
This commit is contained in:
parent
219445d03a
commit
24bbb68d38
@ -289,6 +289,12 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
|
||||
void process(JavapTask task, String opt, String arg) {
|
||||
task.options.showConstants = true;
|
||||
}
|
||||
},
|
||||
|
||||
new Option(false, "-XDinner") {
|
||||
void process(JavapTask task, String opt, String arg) {
|
||||
task.options.showInnerClasses = true;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@ -529,46 +535,15 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
|
||||
SourceWriter sourceWriter = SourceWriter.instance(context);
|
||||
sourceWriter.setFileManager(fileManager);
|
||||
|
||||
attributeFactory.setCompat(options.compat);
|
||||
attributeFactory.setJSR277(options.jsr277);
|
||||
|
||||
boolean ok = true;
|
||||
|
||||
for (String className: classes) {
|
||||
JavaFileObject fo;
|
||||
try {
|
||||
if (className.endsWith(".class")) {
|
||||
if (fileManager instanceof StandardJavaFileManager) {
|
||||
StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
|
||||
fo = sfm.getJavaFileObjects(className).iterator().next();
|
||||
} else {
|
||||
reportError("err.not.standard.file.manager", className);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
fo = getClassFileObject(className);
|
||||
if (fo == null) {
|
||||
// see if it is an inner class, by replacing dots to $, starting from the right
|
||||
String cn = className;
|
||||
int lastDot;
|
||||
while (fo == null && (lastDot = cn.lastIndexOf(".")) != -1) {
|
||||
cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
|
||||
fo = getClassFileObject(cn);
|
||||
}
|
||||
}
|
||||
if (fo == null) {
|
||||
reportError("err.class.not.found", className);
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
attributeFactory.setCompat(options.compat);
|
||||
attributeFactory.setJSR277(options.jsr277);
|
||||
ClassFileInfo cfInfo = read(fo);
|
||||
if (!className.endsWith(".class")) {
|
||||
String cfName = cfInfo.cf.getName();
|
||||
if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", ".")))
|
||||
reportWarning("warn.unexpected.class", className, cfName.replace('/', '.'));
|
||||
}
|
||||
write(cfInfo);
|
||||
writeClass(classWriter, className);
|
||||
} catch (ConstantPoolException e) {
|
||||
reportError("err.bad.constant.pool", className, e.getLocalizedMessage());
|
||||
ok = false;
|
||||
@ -598,6 +573,76 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
|
||||
return ok;
|
||||
}
|
||||
|
||||
protected boolean writeClass(ClassWriter classWriter, String className)
|
||||
throws IOException, ConstantPoolException {
|
||||
JavaFileObject fo;
|
||||
if (className.endsWith(".class")) {
|
||||
if (fileManager instanceof StandardJavaFileManager) {
|
||||
StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
|
||||
fo = sfm.getJavaFileObjects(className).iterator().next();
|
||||
} else {
|
||||
reportError("err.not.standard.file.manager", className);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
fo = getClassFileObject(className);
|
||||
if (fo == null) {
|
||||
// see if it is an inner class, by replacing dots to $, starting from the right
|
||||
String cn = className;
|
||||
int lastDot;
|
||||
while (fo == null && (lastDot = cn.lastIndexOf(".")) != -1) {
|
||||
cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
|
||||
fo = getClassFileObject(cn);
|
||||
}
|
||||
}
|
||||
if (fo == null) {
|
||||
reportError("err.class.not.found", className);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ClassFileInfo cfInfo = read(fo);
|
||||
if (!className.endsWith(".class")) {
|
||||
String cfName = cfInfo.cf.getName();
|
||||
if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", ".")))
|
||||
reportWarning("warn.unexpected.class", className, cfName.replace('/', '.'));
|
||||
}
|
||||
write(cfInfo);
|
||||
|
||||
if (options.showInnerClasses) {
|
||||
ClassFile cf = cfInfo.cf;
|
||||
Attribute a = cf.getAttribute(Attribute.InnerClasses);
|
||||
if (a instanceof InnerClasses_attribute) {
|
||||
InnerClasses_attribute inners = (InnerClasses_attribute) a;
|
||||
try {
|
||||
boolean ok = true;
|
||||
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();
|
||||
classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", "."));
|
||||
classWriter.println();
|
||||
ok = ok & writeClass(classWriter, innerClassName);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
} catch (ConstantPoolException e) {
|
||||
reportError("err.bad.innerclasses.attribute", className);
|
||||
return false;
|
||||
}
|
||||
} else if (a != null) {
|
||||
reportError("err.bad.innerclasses.attribute", className);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class ClassFileInfo {
|
||||
ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {
|
||||
this.fo = fo;
|
||||
@ -801,6 +846,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
|
||||
return JavapTask.this.getMessage(locale, key, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]";
|
||||
}
|
||||
|
||||
@ -85,6 +85,7 @@ public class Options {
|
||||
public boolean showAllAttrs;
|
||||
public boolean showConstants;
|
||||
public boolean sysInfo;
|
||||
public boolean showInnerClasses;
|
||||
|
||||
public boolean compat; // bug-for-bug compatibility mode with old javap
|
||||
public boolean jsr277;
|
||||
|
||||
@ -18,6 +18,7 @@ err.unknown.option=unknown option: {0}
|
||||
err.verify.not.supported=-verify not supported
|
||||
err.no.SourceFile.attribute=no SourceFile attribute
|
||||
err.source.file.not.found=source file not found
|
||||
err.bad.innerclasses.attribute=bad InnerClasses attribute for {0}
|
||||
warn.Xold.not.supported=-Xold is no longer available
|
||||
|
||||
main.usage.summary=\
|
||||
|
||||
86
langtools/test/tools/javap/T4880672.java
Normal file
86
langtools/test/tools/javap/T4880672.java
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4880672
|
||||
* @summary javap does not output inner interfaces of an interface
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class T4880672
|
||||
{
|
||||
public static void main(String... args) {
|
||||
new T4880672().run();
|
||||
}
|
||||
|
||||
void run() {
|
||||
verify("java.util.Map", "public interface java.util.Map$Entry");
|
||||
verify("T4880672", "class T4880672$A$B extends java.lang.Object");
|
||||
verify("C", ""); // must not give error if no InnerClasses attribute
|
||||
if (errors > 0)
|
||||
throw new Error(errors + " found.");
|
||||
}
|
||||
|
||||
void verify(String className, String... expects) {
|
||||
String output = javap(className);
|
||||
for (String expect: expects) {
|
||||
if (output.indexOf(expect)< 0)
|
||||
error(expect + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
void error(String msg) {
|
||||
System.err.println(msg);
|
||||
errors++;
|
||||
}
|
||||
|
||||
int errors;
|
||||
|
||||
String javap(String className) {
|
||||
String testClasses = System.getProperty("test.classes", ".");
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter out = new PrintWriter(sw);
|
||||
String[] args = { "-XDinner", "-classpath", testClasses, className };
|
||||
int rc = com.sun.tools.javap.Main.run(args, out);
|
||||
out.close();
|
||||
String output = sw.toString();
|
||||
System.out.println("class " + className);
|
||||
System.out.println(output);
|
||||
if (rc != 0)
|
||||
throw new Error("javap failed. rc=" + rc);
|
||||
if (output.indexOf("Error:") != -1)
|
||||
throw new Error("javap reported error.");
|
||||
return output;
|
||||
}
|
||||
|
||||
class A {
|
||||
class B { }
|
||||
}
|
||||
}
|
||||
|
||||
class C { }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user