TraceClassVisitorpublic class TraceClassVisitor extends PrintClassVisitor A {@link PrintClassVisitor PrintClassVisitor} that prints a disassembled
view of the classes it visits. This class visitor can be used alone (see the
{@link #main main} method) to disassemble a class. It can also be used in
the middle of class visitor chain to trace the class that is visited at a
given point in this chain. This may be uselful for debugging purposes.
The trace printed when visiting the Hello class is the following:
// compiled from Hello.java
public class Hello {
public static main ([Ljava/lang/String;)V
GETSTATIC java/lang/System out Ljava/io/PrintStream;
LDC "hello"
INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V
RETURN
MAXSTACK = 2
MAXLOCALS = 1
public <init> ()V
ALOAD 0
INVOKESPECIAL java/lang/Object <init> ()V
RETURN
MAXSTACK = 1
MAXLOCALS = 1
}
where Hello is defined by:
public class Hello {
public static void main (String[] args) {
System.out.println("hello");
}
}
|
Fields Summary |
---|
protected final ClassVisitor | cvThe {@link ClassVisitor ClassVisitor} to which this visitor delegates
calls. May be null. |
Constructors Summary |
---|
public TraceClassVisitor(ClassVisitor cv, PrintWriter pw)Constructs a new {@link TraceClassVisitor TraceClassVisitor} object.
super(pw);
this.cv = cv;
|
Methods Summary |
---|
private void | appendAccess(int access)Appends a string representation of the given access modifiers to {@link
#buf buf}.
if ((access & Constants.ACC_PUBLIC) != 0) {
buf.append("public ");
}
if ((access & Constants.ACC_PRIVATE) != 0) {
buf.append("private ");
}
if ((access & Constants.ACC_PROTECTED) != 0) {
buf.append("protected ");
}
if ((access & Constants.ACC_FINAL) != 0) {
buf.append("final ");
}
if ((access & Constants.ACC_STATIC) != 0) {
buf.append("static ");
}
if ((access & Constants.ACC_SYNCHRONIZED) != 0) {
buf.append("synchronized ");
}
if ((access & Constants.ACC_VOLATILE) != 0) {
buf.append("volatile ");
}
if ((access & Constants.ACC_TRANSIENT) != 0) {
buf.append("transient ");
}
// if ((access & Constants.ACC_NATIVE) != 0) {
// buf.append("native ");
// }
if ((access & Constants.ACC_ABSTRACT) != 0) {
buf.append("abstract ");
}
if ((access & Constants.ACC_STRICT) != 0) {
buf.append("strictfp ");
}
| public static void | main(java.lang.String[] args)Prints a disassembled view of the given class to the standard output.
Usage: TraceClassVisitor [-debug]
<fully qualified class name or class file name >
if (args.length < 1 || args.length > 2) {
printUsage();
}
int i = 0;
boolean skipDebug = true;
if (args[0].equals("-debug")) {
i = 1;
skipDebug = false;
if (args.length != 2) {
printUsage();
}
}
ClassReader cr;
if (args[i].endsWith(".class")) {
cr = new ClassReader(new FileInputStream(args[i]));
} else {
cr = new ClassReader(args[i]);
}
cr.accept(new TraceClassVisitor(
null, new PrintWriter(System.out)), getDefaultAttributes(), skipDebug);
| private static void | printUsage()
System.err.println("Prints a disassembled view of the given class.");
System.err.println("Usage: TraceClassVisitor [-debug] " +
"<fully qualified class name or class file name>");
System.exit(-1);
| public void | visit(int version, int access, java.lang.String name, java.lang.String superName, java.lang.String[] interfaces, java.lang.String sourceFile)
int major = version & 0xFFFF;
int minor = version >>> 16;
buf.setLength(0);
buf.append("// class version " + major + "." + minor + " (" + version + ")\n");
if ((access & Constants.ACC_DEPRECATED) != 0) {
buf.append("// DEPRECATED\n");
}
if (sourceFile != null) {
buf.append("// compiled from ").append(sourceFile).append("\n");
}
buf.append("// access flags ").append(access).append("\n");
appendAccess(access & ~Constants.ACC_SUPER);
if ((access & Constants.ACC_ANNOTATION) != 0) {
buf.append("@interface ");
} else if ((access & Constants.ACC_INTERFACE) != 0) {
buf.append("interface ");
} else if ((access & Constants.ACC_ENUM) != 0) {
buf.append("enum ");
} else {
buf.append("class ");
}
buf.append(name).append(" ");
if (superName != null && !superName.equals("java/lang/Object")) {
buf.append("extends ").append(superName).append(" ");
}
if (interfaces != null && interfaces.length > 0) {
buf.append("implements ");
for (int i = 0; i < interfaces.length; ++i) {
buf.append(interfaces[i]).append(" ");
}
}
buf.append("{\n\n");
text.add(buf.toString());
if (cv != null) {
cv.visit(version, access, name, superName, interfaces, sourceFile);
}
| public void | visitAttribute(oracle.toplink.libraries.asm.Attribute attr)
buf.setLength(0);
buf.append(" CLASS ATTRIBUTE ").append(attr.type).append(" : ")
.append(attr.toString()).append("\n");
text.add(buf.toString());
if (cv != null) {
cv.visitAttribute(attr);
}
| public void | visitEnd()
text.add("}\n");
if (cv != null) {
cv.visitEnd();
}
super.visitEnd();
| public void | visitField(int access, java.lang.String name, java.lang.String desc, java.lang.Object value, oracle.toplink.libraries.asm.Attribute attrs)
buf.setLength(0);
if ((access & Constants.ACC_DEPRECATED) != 0) {
buf.append(" // DEPRECATED\n");
}
buf.append(" // access flags ").append(access).append("\n");
buf.append(" ");
appendAccess(access);
if ((access & Constants.ACC_ENUM) != 0) {
buf.append("enum ");
}
buf.append(desc)
.append(" ")
.append(name);
if (value != null) {
buf.append(" = ");
if (value instanceof String) {
buf.append("\"").append(value).append("\"");
} else {
buf.append(value);
}
}
Attribute attr = attrs;
while (attr != null) {
buf.append(" FIELD ATTRIBUTE ").append(attr.type).append(" : ")
.append(attr.toString()).append("\n");
attr = attr.next;
}
buf.append("\n");
text.add(buf.toString());
if (cv != null) {
cv.visitField(access, name, desc, value, attrs);
}
| public void | visitInnerClass(java.lang.String name, java.lang.String outerName, java.lang.String innerName, int access)
buf.setLength(0);
buf.append(" INNERCLASS ")
.append(name)
.append(" ")
.append(outerName)
.append(" ")
.append(innerName)
.append(" ");
appendAccess(access & ~Constants.ACC_SUPER);
if ((access & Constants.ACC_ENUM) != 0) {
buf.append("enum ");
}
buf.append("\n");
text.add(buf.toString());
if (cv != null) {
cv.visitInnerClass(name, outerName, innerName, access);
}
| public oracle.toplink.libraries.asm.CodeVisitor | visitMethod(int access, java.lang.String name, java.lang.String desc, java.lang.String[] exceptions, oracle.toplink.libraries.asm.Attribute attrs)
buf.setLength(0);
if ((access & Constants.ACC_DEPRECATED) != 0) {
buf.append(" // DEPRECATED\n");
}
buf.append(" // access flags ").append(access).append("\n");
buf.append(" ");
appendAccess(access);
if ((access & Constants.ACC_NATIVE) != 0) {
buf.append("native ");
}
if ((access & Constants.ACC_VARARGS) != 0) {
buf.append("varargs ");
}
if ((access & Constants.ACC_BRIDGE) != 0) {
buf.append("bridge ");
}
buf.append(name).
append(" ").
append(desc);
if (exceptions != null && exceptions.length > 0) {
buf.append(" throws ");
for (int i = 0; i < exceptions.length; ++i) {
buf.append(exceptions[i]).append(" ");
}
}
buf.append("\n");
text.add(buf.toString());
Attribute attr = attrs;
while (attr != null) {
buf.setLength(0);
buf.append(" METHOD ATTRIBUTE ").append(attr.type).append(" : ")
.append(attr.toString()).append("\n");
text.add(buf.toString());
attr = attr.next;
}
CodeVisitor cv;
if (this.cv != null) {
cv = this.cv.visitMethod(access, name, desc, exceptions, attrs);
} else {
cv = null;
}
PrintCodeVisitor pcv = new TraceCodeVisitor(cv);
text.add(pcv.getText());
return pcv;
|
|