mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
4075303: Use javap to enquire aboput a specific inner class
4348375: Javap is not internationalized 4459541: "javap -l" shows line numbers as signed short; they should be unsigned 4501660: change diagnostic of -help as 'print this help message and exit' 4776241: unused source file in javap.. 4870651: javap should recognize generics, varargs, enum 4876942: javap invoked without args does not print help screen 4880663: javap could output whitespace between class name and opening brace 4975569: javap doesn't print new flag bits 6271787: javap dumps LocalVariableTypeTable attribute in hex, needs to print a table 6305779: javap: support annotations 6439940: Clean up javap implementation 6469569: wrong check of searchpath in JavapEnvironment 6474890: javap does not open .zip files in -classpath 6587786: Javap throws error : "ERROR:Could not find <classname>" for JRE classes 6622215: javap ignores certain relevant access flags 6622216: javap names some attributes incorrectly 6622232: javap gets whitespace confused 6622260: javap prints negative bytes incorrectly in hex Reviewed-by: ksrini
This commit is contained in:
parent
e3ba3ecd1d
commit
0a7516d744
87 changed files with 11690 additions and 8 deletions
488
langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java
Normal file
488
langtools/src/share/classes/com/sun/tools/javap/ClassWriter.java
Normal file
|
@ -0,0 +1,488 @@
|
|||
/*
|
||||
* Copyright 2007 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.tools.classfile.AccessFlags;
|
||||
import com.sun.tools.classfile.Attribute;
|
||||
import com.sun.tools.classfile.Attributes;
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.Code_attribute;
|
||||
import com.sun.tools.classfile.ConstantPool;
|
||||
import com.sun.tools.classfile.ConstantPoolException;
|
||||
import com.sun.tools.classfile.Descriptor;
|
||||
import com.sun.tools.classfile.DescriptorException;
|
||||
import com.sun.tools.classfile.Exceptions_attribute;
|
||||
import com.sun.tools.classfile.Field;
|
||||
import com.sun.tools.classfile.Method;
|
||||
import com.sun.tools.classfile.Signature;
|
||||
import com.sun.tools.classfile.Signature_attribute;
|
||||
import com.sun.tools.classfile.SourceFile_attribute;
|
||||
import com.sun.tools.classfile.Type;
|
||||
|
||||
import static com.sun.tools.classfile.AccessFlags.*;
|
||||
|
||||
/*
|
||||
* The main javap class to write the contents of a class file as text.
|
||||
*
|
||||
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
|
||||
* you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class ClassWriter extends BasicWriter {
|
||||
static ClassWriter instance(Context context) {
|
||||
ClassWriter instance = context.get(ClassWriter.class);
|
||||
if (instance == null)
|
||||
instance = new ClassWriter(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected ClassWriter(Context context) {
|
||||
super(context);
|
||||
context.put(ClassWriter.class, this);
|
||||
options = Options.instance(context);
|
||||
attrWriter = AttributeWriter.instance(context);
|
||||
codeWriter = CodeWriter.instance(context);
|
||||
constantWriter = ConstantWriter.instance(context);
|
||||
}
|
||||
|
||||
ClassFile getClassFile() {
|
||||
return classFile;
|
||||
}
|
||||
|
||||
Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void write(ClassFile cf) {
|
||||
classFile = cf;
|
||||
constant_pool = classFile.constant_pool;
|
||||
|
||||
Attribute sfa = cf.getAttribute(Attribute.SourceFile);
|
||||
if (sfa instanceof SourceFile_attribute) {
|
||||
println("Compiled from \"" + getSourceFile((SourceFile_attribute) sfa) + "\"");
|
||||
}
|
||||
|
||||
String name = getJavaName(classFile);
|
||||
AccessFlags flags = cf.access_flags;
|
||||
|
||||
writeModifiers(flags.getClassModifiers());
|
||||
|
||||
if (classFile.isClass())
|
||||
print("class ");
|
||||
else if (classFile.isInterface())
|
||||
print("interface ");
|
||||
|
||||
print(name);
|
||||
|
||||
Signature_attribute sigAttr = getSignature(cf.attributes);
|
||||
if (sigAttr == null) {
|
||||
// use info from class file header
|
||||
if (classFile.isClass()) {
|
||||
if (classFile.super_class != 0 ) {
|
||||
String sn = getJavaSuperclassName(cf);
|
||||
if (!sn.equals("java.lang.Object") || options.compat) { // BUG XXXXXXXX
|
||||
print(" extends ");
|
||||
print(sn);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < classFile.interfaces.length; i++) {
|
||||
print(i == 0 ? (classFile.isClass() ? " implements " : " extends ") : ",");
|
||||
print(getJavaInterfaceName(classFile, i));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Type t = sigAttr.getParsedSignature().getType(constant_pool);
|
||||
// The signature parser cannot disambiguate between a
|
||||
// FieldType and a ClassSignatureType that only contains a superclass type.
|
||||
if (t instanceof Type.ClassSigType)
|
||||
print(t);
|
||||
else if (!t.isObject()) {
|
||||
print(" extends ");
|
||||
print(t);
|
||||
}
|
||||
} catch (ConstantPoolException e) {
|
||||
print(report(e));
|
||||
}
|
||||
}
|
||||
|
||||
if (options.verbose) {
|
||||
println();
|
||||
attrWriter.write(cf, cf.attributes, constant_pool);
|
||||
println(" minor version: " + cf.minor_version);
|
||||
println(" major version: " + cf.major_version);
|
||||
if (!options.compat)
|
||||
writeList(" flags: ", flags.getClassFlags(), NEWLINE);
|
||||
constantWriter.writeConstantPool();
|
||||
println();
|
||||
} else {
|
||||
if (!options.compat)
|
||||
print(" ");
|
||||
}
|
||||
|
||||
println("{");
|
||||
writeFields();
|
||||
writeMethods();
|
||||
println("}");
|
||||
println();
|
||||
}
|
||||
|
||||
void writeFields() {
|
||||
for (Field f: classFile.fields) {
|
||||
writeField(f);
|
||||
}
|
||||
}
|
||||
|
||||
void writeField(Field f) {
|
||||
if (!options.checkAccess(f.access_flags))
|
||||
return;
|
||||
|
||||
if (!(options.showLineAndLocalVariableTables
|
||||
|| options.showDisassembled
|
||||
|| options.verbose
|
||||
|| options.showInternalSignatures
|
||||
|| options.showAllAttrs)) {
|
||||
print(" ");
|
||||
}
|
||||
|
||||
AccessFlags flags = f.access_flags;
|
||||
writeModifiers(flags.getFieldModifiers());
|
||||
Signature_attribute sigAttr = getSignature(f.attributes);
|
||||
if (sigAttr == null)
|
||||
print(getFieldType(f.descriptor));
|
||||
else {
|
||||
try {
|
||||
Type t = sigAttr.getParsedSignature().getType(constant_pool);
|
||||
print(t);
|
||||
} catch (ConstantPoolException e) {
|
||||
// report error?
|
||||
// fall back on non-generic descriptor
|
||||
print(getFieldType(f.descriptor));
|
||||
}
|
||||
}
|
||||
print(" ");
|
||||
print(getFieldName(f));
|
||||
print(";");
|
||||
println();
|
||||
|
||||
if (options.showInternalSignatures)
|
||||
println(" Signature: " + getValue(f.descriptor));
|
||||
|
||||
if (options.verbose && !options.compat)
|
||||
writeList(" flags: ", flags.getFieldFlags(), NEWLINE);
|
||||
|
||||
if (options.showAllAttrs) {
|
||||
for (Attribute attr: f.attributes)
|
||||
attrWriter.write(f, attr, constant_pool);
|
||||
println();
|
||||
}
|
||||
|
||||
if (options.showDisassembled || options.showLineAndLocalVariableTables)
|
||||
println();
|
||||
}
|
||||
|
||||
void writeMethods() {
|
||||
for (Method m: classFile.methods)
|
||||
writeMethod(m);
|
||||
}
|
||||
|
||||
void writeMethod(Method m) {
|
||||
if (!options.checkAccess(m.access_flags))
|
||||
return;
|
||||
|
||||
method = m;
|
||||
|
||||
if (!(options.showLineAndLocalVariableTables
|
||||
|| options.showDisassembled
|
||||
|| options.verbose
|
||||
|| options.showInternalSignatures
|
||||
|| options.showAllAttrs)) {
|
||||
print(" ");
|
||||
}
|
||||
|
||||
AccessFlags flags = m.access_flags;
|
||||
|
||||
Descriptor d;
|
||||
Type.MethodType methodType;
|
||||
List<? extends Type> methodExceptions;
|
||||
|
||||
Signature_attribute sigAttr = getSignature(m.attributes);
|
||||
if (sigAttr == null) {
|
||||
d = m.descriptor;
|
||||
methodType = null;
|
||||
methodExceptions = null;
|
||||
} else {
|
||||
Signature methodSig = sigAttr.getParsedSignature();
|
||||
d = methodSig;
|
||||
try {
|
||||
methodType = (Type.MethodType) methodSig.getType(constant_pool);
|
||||
methodExceptions = methodType.throwsTypes;
|
||||
if (methodExceptions != null && methodExceptions.size() == 0)
|
||||
methodExceptions = null;
|
||||
} catch (ConstantPoolException e) {
|
||||
// report error?
|
||||
// fall back on standard descriptor
|
||||
methodType = null;
|
||||
methodExceptions = null;
|
||||
}
|
||||
}
|
||||
|
||||
writeModifiers(flags.getMethodModifiers());
|
||||
if (methodType != null) {
|
||||
writeListIfNotEmpty("<", methodType.typeArgTypes, "> ");
|
||||
}
|
||||
if (getName(m).equals("<init>")) {
|
||||
print(getJavaName(classFile));
|
||||
print(getParameterTypes(d, flags));
|
||||
} else if (getName(m).equals("<clinit>")) {
|
||||
print("{}");
|
||||
} else {
|
||||
print(getReturnType(d));
|
||||
print(" ");
|
||||
print(getName(m));
|
||||
print(getParameterTypes(d, flags));
|
||||
}
|
||||
|
||||
Attribute e_attr = m.attributes.get(Attribute.Exceptions);
|
||||
if (e_attr != null) { // if there are generic exceptions, there must be erased exceptions
|
||||
if (e_attr instanceof Exceptions_attribute) {
|
||||
Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
|
||||
if (options.compat) { // Bug XXXXXXX whitespace
|
||||
if (!(options.showLineAndLocalVariableTables
|
||||
|| options.showDisassembled
|
||||
|| options.verbose
|
||||
|| options.showInternalSignatures
|
||||
|| options.showAllAttrs)) {
|
||||
print(" ");
|
||||
}
|
||||
print(" ");
|
||||
}
|
||||
print(" throws ");
|
||||
if (methodExceptions != null) { // use generic list if available
|
||||
writeList("", methodExceptions, "");
|
||||
} else {
|
||||
for (int i = 0; i < exceptions.number_of_exceptions; i++) {
|
||||
if (i > 0)
|
||||
print(", ");
|
||||
print(attrWriter.getJavaException(exceptions, i));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
report("Unexpected or invalid value for Exceptions attribute");
|
||||
}
|
||||
}
|
||||
|
||||
print(";");
|
||||
println();
|
||||
|
||||
if (options.showInternalSignatures)
|
||||
println(" Signature: " + getValue(m.descriptor));
|
||||
|
||||
if (options.verbose && !options.compat)
|
||||
writeList(" flags: ", flags.getMethodFlags(), NEWLINE);
|
||||
|
||||
Code_attribute code = null;
|
||||
Attribute c_attr = m.attributes.get(Attribute.Code);
|
||||
if (c_attr != null) {
|
||||
if (c_attr instanceof Code_attribute)
|
||||
code = (Code_attribute) c_attr;
|
||||
else
|
||||
report("Unexpected or invalid value for Code attribute");
|
||||
}
|
||||
|
||||
if (options.showDisassembled && !options.showAllAttrs) {
|
||||
if (code != null) {
|
||||
println(" Code:");
|
||||
codeWriter.writeInstrs(code);
|
||||
codeWriter.writeExceptionTable(code);
|
||||
}
|
||||
println();
|
||||
}
|
||||
|
||||
if (options.showLineAndLocalVariableTables) {
|
||||
if (code != null)
|
||||
attrWriter.write(code, code.attributes.get(Attribute.LineNumberTable), constant_pool);
|
||||
println();
|
||||
if (code != null)
|
||||
attrWriter.write(code, code.attributes.get(Attribute.LocalVariableTable), constant_pool);
|
||||
println();
|
||||
println();
|
||||
}
|
||||
|
||||
if (options.showAllAttrs) {
|
||||
Attribute[] attrs = m.attributes.attrs;
|
||||
for (Attribute attr: attrs)
|
||||
attrWriter.write(m, attr, constant_pool);
|
||||
|
||||
// // the following condition is to mimic old javap
|
||||
// if (!(attrs.length > 0 &&
|
||||
// attrs[attrs.length - 1] instanceof Exceptions_attribute))
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void writeModifiers(Collection<String> items) {
|
||||
for (Object item: items) {
|
||||
print(item);
|
||||
print(" ");
|
||||
}
|
||||
}
|
||||
|
||||
void writeList(String prefix, Collection<?> items, String suffix) {
|
||||
print(prefix);
|
||||
String sep = "";
|
||||
for (Object item: items) {
|
||||
print(sep);
|
||||
print(item);
|
||||
sep = ", ";
|
||||
}
|
||||
print(suffix);
|
||||
}
|
||||
|
||||
void writeListIfNotEmpty(String prefix, List<?> items, String suffix) {
|
||||
if (items != null && items.size() > 0)
|
||||
writeList(prefix, items, suffix);
|
||||
}
|
||||
|
||||
Signature_attribute getSignature(Attributes attributes) {
|
||||
if (options.compat) // javap does not recognize recent attributes
|
||||
return null;
|
||||
return (Signature_attribute) attributes.get(Attribute.Signature);
|
||||
}
|
||||
|
||||
String adjustVarargs(AccessFlags flags, String params) {
|
||||
if (flags.is(ACC_VARARGS) && !options.compat) {
|
||||
int i = params.lastIndexOf("[]");
|
||||
if (i > 0)
|
||||
return params.substring(0, i) + "..." + params.substring(i+2);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
String getJavaName(ClassFile cf) {
|
||||
try {
|
||||
return getJavaName(cf.getName());
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getJavaSuperclassName(ClassFile cf) {
|
||||
try {
|
||||
return getJavaName(cf.getSuperclassName());
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getJavaInterfaceName(ClassFile cf, int index) {
|
||||
try {
|
||||
return getJavaName(cf.getInterfaceName(index));
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getFieldType(Descriptor d) {
|
||||
try {
|
||||
return d.getFieldType(constant_pool);
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
} catch (DescriptorException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getReturnType(Descriptor d) {
|
||||
try {
|
||||
return d.getReturnType(constant_pool);
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
} catch (DescriptorException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getParameterTypes(Descriptor d, AccessFlags flags) {
|
||||
try {
|
||||
return adjustVarargs(flags, d.getParameterTypes(constant_pool));
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
} catch (DescriptorException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getValue(Descriptor d) {
|
||||
try {
|
||||
return d.getValue(constant_pool);
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getFieldName(Field f) {
|
||||
try {
|
||||
return f.getName(constant_pool);
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
String getName(Method m) {
|
||||
try {
|
||||
return m.getName(constant_pool);
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
static String getJavaName(String name) {
|
||||
return name.replace('/', '.');
|
||||
}
|
||||
|
||||
String getSourceFile(SourceFile_attribute attr) {
|
||||
try {
|
||||
return attr.getSourceFile(constant_pool);
|
||||
} catch (ConstantPoolException e) {
|
||||
return report(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Options options;
|
||||
private AttributeWriter attrWriter;
|
||||
private CodeWriter codeWriter;
|
||||
private ConstantWriter constantWriter;
|
||||
private ClassFile classFile;
|
||||
private ConstantPool constant_pool;
|
||||
private Method method;
|
||||
private static final String NEWLINE = System.getProperty("line.separator", "\n");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue