blob: 9af8f755796723f37cecbf226663066b77f79de2 [file] [log] [blame]
/*
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
* Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program 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 for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package proguard.classfile.visitor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
import proguard.classfile.attribute.annotation.target.*;
import proguard.classfile.attribute.annotation.target.visitor.*;
import proguard.classfile.attribute.annotation.visitor.*;
import proguard.classfile.attribute.preverification.*;
import proguard.classfile.attribute.preverification.visitor.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.*;
import java.io.PrintStream;
/**
* This <code>ClassVisitor</code> prints out the complete internal
* structure of the classes it visits.
*
* @author Eric Lafortune
*/
public class ClassPrinter
extends SimplifiedVisitor
implements ClassVisitor,
ConstantVisitor,
MemberVisitor,
AttributeVisitor,
BootstrapMethodInfoVisitor,
InnerClassesInfoVisitor,
ExceptionInfoVisitor,
StackMapFrameVisitor,
VerificationTypeVisitor,
LineNumberInfoVisitor,
ParameterInfoVisitor,
LocalVariableInfoVisitor,
LocalVariableTypeInfoVisitor,
AnnotationVisitor,
TypeAnnotationVisitor,
TargetInfoVisitor,
LocalVariableTargetElementVisitor,
TypePathInfoVisitor,
ElementValueVisitor,
InstructionVisitor
{
private static final String INDENTATION = " ";
private final PrintStream ps;
private int indentation;
/**
* Creates a new ClassPrinter that prints to <code>System.out</code>.
*/
public ClassPrinter()
{
this(System.out);
}
/**
* Creates a new ClassPrinter that prints to the given
* <code>PrintStream</code>.
*/
public ClassPrinter(PrintStream printStream)
{
ps = printStream;
}
// Implementations for ClassVisitor.
public void visitProgramClass(ProgramClass programClass)
{
println("_____________________________________________________________________");
println(visitorInfo(programClass) + " " +
"Program class: " + programClass.getName());
indent();
println("Superclass: " + programClass.getSuperName());
println("Major version: 0x" + Integer.toHexString(ClassUtil.internalMajorClassVersion(programClass.u4version)));
println("Minor version: 0x" + Integer.toHexString(ClassUtil.internalMinorClassVersion(programClass.u4version)));
println(" = target " + ClassUtil.externalClassVersion(programClass.u4version));
println("Access flags: 0x" + Integer.toHexString(programClass.u2accessFlags));
println(" = " +
((programClass.u2accessFlags & ClassConstants.ACC_ANNOTATTION) != 0 ? "@ " : "") +
ClassUtil.externalClassAccessFlags(programClass.u2accessFlags) +
((programClass.u2accessFlags & ClassConstants.ACC_ENUM) != 0 ? "enum " :
(programClass.u2accessFlags & ClassConstants.ACC_INTERFACE) == 0 ? "class " :
"") +
ClassUtil.externalClassName(programClass.getName()) +
(programClass.u2superClass == 0 ? "" : " extends " +
ClassUtil.externalClassName(programClass.getSuperName())));
outdent();
println();
println("Interfaces (count = " + programClass.u2interfacesCount + "):");
indent();
programClass.interfaceConstantsAccept(this);
outdent();
println();
println("Constant Pool (count = " + programClass.u2constantPoolCount + "):");
indent();
programClass.constantPoolEntriesAccept(this);
outdent();
println();
println("Fields (count = " + programClass.u2fieldsCount + "):");
indent();
programClass.fieldsAccept(this);
outdent();
println();
println("Methods (count = " + programClass.u2methodsCount + "):");
indent();
programClass.methodsAccept(this);
outdent();
println();
println("Class file attributes (count = " + programClass.u2attributesCount + "):");
indent();
programClass.attributesAccept(this);
outdent();
println();
}
public void visitLibraryClass(LibraryClass libraryClass)
{
println("_____________________________________________________________________");
println(visitorInfo(libraryClass) + " " +
"Library class: " + libraryClass.getName());
indent();
println("Superclass: " + libraryClass.getSuperName());
println("Access flags: 0x" + Integer.toHexString(libraryClass.u2accessFlags));
println(" = " +
((libraryClass.u2accessFlags & ClassConstants.ACC_ANNOTATTION) != 0 ? "@ " : "") +
ClassUtil.externalClassAccessFlags(libraryClass.u2accessFlags) +
((libraryClass.u2accessFlags & ClassConstants.ACC_ENUM) != 0 ? "enum " :
(libraryClass.u2accessFlags & ClassConstants.ACC_INTERFACE) == 0 ? "class " :
"") +
ClassUtil.externalClassName(libraryClass.getName()) +
(libraryClass.getSuperName() == null ? "" : " extends " +
ClassUtil.externalClassName(libraryClass.getSuperName())));
outdent();
println();
println("Interfaces (count = " + libraryClass.interfaceClasses.length + "):");
for (int index = 0; index < libraryClass.interfaceClasses.length; index++)
{
Clazz interfaceClass = libraryClass.interfaceClasses[index];
if (interfaceClass != null)
{
println(" + " + interfaceClass.getName());
}
}
println("Fields (count = " + libraryClass.fields.length + "):");
libraryClass.fieldsAccept(this);
println("Methods (count = " + libraryClass.methods.length + "):");
libraryClass.methodsAccept(this);
}
// Implementations for ConstantVisitor.
public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
{
println(visitorInfo(integerConstant) + " Integer [" +
integerConstant.getValue() + "]");
}
public void visitLongConstant(Clazz clazz, LongConstant longConstant)
{
println(visitorInfo(longConstant) + " Long [" +
longConstant.getValue() + "]");
}
public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
{
println(visitorInfo(floatConstant) + " Float [" +
floatConstant.getValue() + "]");
}
public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
{
println(visitorInfo(doubleConstant) + " Double [" +
doubleConstant.getValue() + "]");
}
public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
{
println(visitorInfo(stringConstant) + " String [" +
stringConstant.getString(clazz) + "]");
}
public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
{
println(visitorInfo(utf8Constant) + " Utf8 [" +
utf8Constant.getString() + "]");
}
public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
{
println(visitorInfo(invokeDynamicConstant) + " InvokeDynamic [bootstrap method index = " + invokeDynamicConstant.u2bootstrapMethodAttributeIndex + "]:");
indent();
clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this);
outdent();
}
public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
{
println(visitorInfo(methodHandleConstant) + " MethodHandle [kind = " + methodHandleConstant.u1referenceKind + "]:");
indent();
clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
outdent();
}
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
{
println(visitorInfo(fieldrefConstant) + " Fieldref [" +
clazz.getClassName(fieldrefConstant.u2classIndex) + "." +
clazz.getName(fieldrefConstant.u2nameAndTypeIndex) + " " +
clazz.getType(fieldrefConstant.u2nameAndTypeIndex) + "]");
}
public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant)
{
println(visitorInfo(interfaceMethodrefConstant) + " InterfaceMethodref [" +
clazz.getClassName(interfaceMethodrefConstant.u2classIndex) + "." +
clazz.getName(interfaceMethodrefConstant.u2nameAndTypeIndex) + " " +
clazz.getType(interfaceMethodrefConstant.u2nameAndTypeIndex) + "]");
}
public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
{
println(visitorInfo(methodrefConstant) + " Methodref [" +
clazz.getClassName(methodrefConstant.u2classIndex) + "." +
clazz.getName(methodrefConstant.u2nameAndTypeIndex) + " " +
clazz.getType(methodrefConstant.u2nameAndTypeIndex) + "]");
}
public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
{
println(visitorInfo(classConstant) + " Class [" +
classConstant.getName(clazz) + "]");
}
public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
{
println(visitorInfo(methodTypeConstant) + " MethodType [" +
methodTypeConstant.getType(clazz) + "]");
}
public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
{
println(visitorInfo(nameAndTypeConstant) + " NameAndType [" +
nameAndTypeConstant.getName(clazz) + " " +
nameAndTypeConstant.getType(clazz) + "]");
}
// Implementations for MemberVisitor.
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
println(visitorInfo(programField) + " " +
"Field: " +
programField.getName(programClass) + " " +
programField.getDescriptor(programClass));
indent();
println("Access flags: 0x" + Integer.toHexString(programField.u2accessFlags));
println(" = " +
ClassUtil.externalFullFieldDescription(programField.u2accessFlags,
programField.getName(programClass),
programField.getDescriptor(programClass)));
visitMember(programClass, programField);
outdent();
}
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
println(visitorInfo(programMethod) + " " +
"Method: " +
programMethod.getName(programClass) +
programMethod.getDescriptor(programClass));
indent();
println("Access flags: 0x" + Integer.toHexString(programMethod.u2accessFlags));
println(" = " +
ClassUtil.externalFullMethodDescription(programClass.getName(),
programMethod.u2accessFlags,
programMethod.getName(programClass),
programMethod.getDescriptor(programClass)));
visitMember(programClass, programMethod);
outdent();
}
private void visitMember(ProgramClass programClass, ProgramMember programMember)
{
if (programMember.u2attributesCount > 0)
{
println("Class member attributes (count = " + programMember.u2attributesCount + "):");
programMember.attributesAccept(programClass, this);
}
}
public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
{
println(visitorInfo(libraryField) + " " +
"Field: " +
libraryField.getName(libraryClass) + " " +
libraryField.getDescriptor(libraryClass));
indent();
println("Access flags: 0x" + Integer.toHexString(libraryField.u2accessFlags));
println(" = " +
ClassUtil.externalFullFieldDescription(libraryField.u2accessFlags,
libraryField.getName(libraryClass),
libraryField.getDescriptor(libraryClass)));
outdent();
}
public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
{
println(visitorInfo(libraryMethod) + " " +
"Method: " +
libraryMethod.getName(libraryClass) + " " +
libraryMethod.getDescriptor(libraryClass));
indent();
println("Access flags: 0x" + Integer.toHexString(libraryMethod.u2accessFlags));
println(" = " +
ClassUtil.externalFullMethodDescription(libraryClass.getName(),
libraryMethod.u2accessFlags,
libraryMethod.getName(libraryClass),
libraryMethod.getDescriptor(libraryClass)));
outdent();
}
// Implementations for AttributeVisitor.
// Note that attributes are typically only referenced once, so we don't
// test if they are marked already.
public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
{
println(visitorInfo(unknownAttribute) +
" Unknown attribute (" + unknownAttribute.getAttributeName(clazz) + ")");
}
public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
{
println(visitorInfo(bootstrapMethodsAttribute) +
" Bootstrap methods attribute (count = " + bootstrapMethodsAttribute.u2bootstrapMethodsCount + "):");
indent();
bootstrapMethodsAttribute.bootstrapMethodEntriesAccept(clazz, this);
outdent();
}
public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
{
println(visitorInfo(sourceFileAttribute) +
" Source file attribute:");
indent();
clazz.constantPoolEntryAccept(sourceFileAttribute.u2sourceFileIndex, this);
outdent();
}
public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
{
println(visitorInfo(sourceDirAttribute) +
" Source dir attribute:");
indent();
clazz.constantPoolEntryAccept(sourceDirAttribute.u2sourceDirIndex, this);
outdent();
}
public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
{
println(visitorInfo(innerClassesAttribute) +
" Inner classes attribute (count = " + innerClassesAttribute.u2classesCount + ")");
indent();
innerClassesAttribute.innerClassEntriesAccept(clazz, this);
outdent();
}
public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
{
println(visitorInfo(enclosingMethodAttribute) +
" Enclosing method attribute:");
indent();
clazz.constantPoolEntryAccept(enclosingMethodAttribute.u2classIndex, this);
if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
{
clazz.constantPoolEntryAccept(enclosingMethodAttribute.u2nameAndTypeIndex, this);
}
outdent();
}
public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
{
println(visitorInfo(deprecatedAttribute) +
" Deprecated attribute");
}
public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
{
println(visitorInfo(syntheticAttribute) +
" Synthetic attribute");
}
public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
{
println(visitorInfo(signatureAttribute) +
" Signature attribute:");
indent();
clazz.constantPoolEntryAccept(signatureAttribute.u2signatureIndex, this);
outdent();
}
public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
{
println(visitorInfo(constantValueAttribute) +
" Constant value attribute:");
clazz.constantPoolEntryAccept(constantValueAttribute.u2constantValueIndex, this);
}
public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
{
println(visitorInfo(methodParametersAttribute) +
" Method parameters attribute (count = " + methodParametersAttribute.u1parametersCount + ")");
indent();
methodParametersAttribute.parametersAccept(clazz, method, this);
outdent();
}
public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
{
println(visitorInfo(exceptionsAttribute) +
" Exceptions attribute (count = " + exceptionsAttribute.u2exceptionIndexTableLength + ")");
indent();
exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
outdent();
}
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
println(visitorInfo(codeAttribute) +
" Code attribute instructions (code length = "+ codeAttribute.u4codeLength +
", locals = "+ codeAttribute.u2maxLocals +
", stack = "+ codeAttribute.u2maxStack + "):");
indent();
codeAttribute.instructionsAccept(clazz, method, this);
println("Code attribute exceptions (count = " +
codeAttribute.u2exceptionTableLength + "):");
codeAttribute.exceptionsAccept(clazz, method, this);
println("Code attribute attributes (attribute count = " +
codeAttribute.u2attributesCount + "):");
codeAttribute.attributesAccept(clazz, method, this);
outdent();
}
public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
{
println(visitorInfo(codeAttribute) +
" Stack map attribute (count = "+
stackMapAttribute.u2stackMapFramesCount + "):");
indent();
stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
outdent();
}
public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
{
println(visitorInfo(codeAttribute) +
" Stack map table attribute (count = "+
stackMapTableAttribute.u2stackMapFramesCount + "):");
indent();
stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
outdent();
}
public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
println(visitorInfo(lineNumberTableAttribute) +
" Line number table attribute (count = " +
lineNumberTableAttribute.u2lineNumberTableLength + ")");
indent();
lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
outdent();
}
public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
{
println(visitorInfo(localVariableTableAttribute) +
" Local variable table attribute (count = " +
localVariableTableAttribute.u2localVariableTableLength + ")");
indent();
localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
outdent();
}
public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
{
println(visitorInfo(localVariableTypeTableAttribute) +
" Local variable type table attribute (count = "+
localVariableTypeTableAttribute.u2localVariableTypeTableLength + ")");
indent();
localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
outdent();
}
public void visitRuntimeVisibleAnnotationsAttribute(Clazz clazz, RuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute)
{
println(visitorInfo(runtimeVisibleAnnotationsAttribute) +
" Runtime visible annotations attribute:");
indent();
runtimeVisibleAnnotationsAttribute.annotationsAccept(clazz, this);
outdent();
}
public void visitRuntimeInvisibleAnnotationsAttribute(Clazz clazz, RuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute)
{
println(visitorInfo(runtimeInvisibleAnnotationsAttribute) +
" Runtime invisible annotations attribute:");
indent();
runtimeInvisibleAnnotationsAttribute.annotationsAccept(clazz, this);
outdent();
}
public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute)
{
println(visitorInfo(runtimeVisibleParameterAnnotationsAttribute) +
" Runtime visible parameter annotations attribute (parameter count = " + runtimeVisibleParameterAnnotationsAttribute.u1parametersCount + "):");
indent();
runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
outdent();
}
public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute)
{
println(visitorInfo(runtimeInvisibleParameterAnnotationsAttribute) +
" Runtime invisible parameter annotations attribute (parameter count = " + runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount + "):");
indent();
runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
outdent();
}
public void visitRuntimeVisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeVisibleTypeAnnotationsAttribute runtimeVisibleTypeAnnotationsAttribute)
{
println(visitorInfo(runtimeVisibleTypeAnnotationsAttribute) +
" Runtime visible type annotations attribute");
indent();
runtimeVisibleTypeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
outdent();
}
public void visitRuntimeInvisibleTypeAnnotationsAttribute(Clazz clazz, RuntimeInvisibleTypeAnnotationsAttribute runtimeInvisibleTypeAnnotationsAttribute)
{
println(visitorInfo(runtimeInvisibleTypeAnnotationsAttribute) +
" Runtime invisible type annotations attribute");
indent();
runtimeInvisibleTypeAnnotationsAttribute.typeAnnotationsAccept(clazz, this);
outdent();
}
public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
{
println(visitorInfo(annotationDefaultAttribute) +
" Annotation default attribute:");
indent();
annotationDefaultAttribute.defaultValueAccept(clazz, this);
outdent();
}
// Implementations for BootstrapMethodInfoVisitor.
public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
{
println(visitorInfo(bootstrapMethodInfo) +
" BootstrapMethodInfo (argument count = " +
bootstrapMethodInfo.u2methodArgumentCount+ "):");
indent();
clazz.constantPoolEntryAccept(bootstrapMethodInfo.u2methodHandleIndex, this);
bootstrapMethodInfo.methodArgumentsAccept(clazz, this);
outdent();
}
// Implementations for InnerClassesInfoVisitor.
public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
{
println(visitorInfo(innerClassesInfo) +
" InnerClassesInfo:");
indent();
println("Access flags: 0x" + Integer.toHexString(innerClassesInfo.u2innerClassAccessFlags) + " = " +
ClassUtil.externalClassAccessFlags(innerClassesInfo.u2innerClassAccessFlags));
innerClassesInfo.innerClassConstantAccept(clazz, this);
innerClassesInfo.outerClassConstantAccept(clazz, this);
innerClassesInfo.innerNameConstantAccept(clazz, this);
outdent();
}
// Implementations for InstructionVisitor.
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
println(instruction.toString(offset));
}
public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
{
println(constantInstruction.toString(offset));
indent();
clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
outdent();
}
public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
{
println(tableSwitchInstruction.toString(offset));
indent();
int[] jumpOffsets = tableSwitchInstruction.jumpOffsets;
for (int index = 0; index < jumpOffsets.length; index++)
{
int jumpOffset = jumpOffsets[index];
println(Integer.toString(tableSwitchInstruction.lowCase + index) + ": offset = " + jumpOffset + ", target = " + (offset + jumpOffset));
}
int defaultOffset = tableSwitchInstruction.defaultOffset;
println("default: offset = " + defaultOffset + ", target = "+ (offset + defaultOffset));
outdent();
}
public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
{
println(lookUpSwitchInstruction.toString(offset));
indent();
int[] cases = lookUpSwitchInstruction.cases;
int[] jumpOffsets = lookUpSwitchInstruction.jumpOffsets;
for (int index = 0; index < jumpOffsets.length; index++)
{
int jumpOffset = jumpOffsets[index];
println(Integer.toString(cases[index]) + ": offset = " + jumpOffset + ", target = " + (offset + jumpOffset));
}
int defaultOffset = lookUpSwitchInstruction.defaultOffset;
println("default: offset = " + defaultOffset + ", target = "+ (offset + defaultOffset));
outdent();
}
// Implementations for ExceptionInfoVisitor.
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
println(visitorInfo(exceptionInfo) +
" ExceptionInfo (" +
exceptionInfo.u2startPC + " -> " +
exceptionInfo.u2endPC + ": " +
exceptionInfo.u2handlerPC + "):");
if (exceptionInfo.u2catchType != 0)
{
clazz.constantPoolEntryAccept(exceptionInfo.u2catchType, this);
}
}
// Implementations for StackMapFrameVisitor.
public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame)
{
println(visitorInfo(sameZeroFrame) +
" [" + offset + "]" +
" Var: ..., Stack: (empty)");
}
public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
{
print(visitorInfo(sameOneFrame) +
" [" + offset + "]" +
" Var: ..., Stack: ");
sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
println();
}
public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame)
{
println(visitorInfo(lessZeroFrame) +
" [" + offset + "]" +
" Var: -" + lessZeroFrame.choppedVariablesCount +
", Stack: (empty)");
}
public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
{
print(visitorInfo(moreZeroFrame) +
" [" + offset + "]" +
" Var: ...");
moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
ps.println(", Stack: (empty)");
}
public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
{
print(visitorInfo(fullFrame) +
" [" + offset + "]" +
" Var: ");
fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
ps.print(", Stack: ");
fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
println();
}
// Implementations for VerificationTypeVisitor.
public void visitIntegerType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, IntegerType integerType)
{
ps.print("[i]");
}
public void visitFloatType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FloatType floatType)
{
ps.print("[f]");
}
public void visitLongType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LongType longType)
{
ps.print("[l]");
}
public void visitDoubleType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, DoubleType doubleType)
{
ps.print("[d]");
}
public void visitTopType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TopType topType)
{
ps.print("[T]");
}
public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
{
ps.print("[a:" + clazz.getClassName(objectType.u2classIndex) + "]");
}
public void visitNullType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, NullType nullType)
{
ps.print("[n]");
}
public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
{
ps.print("[u:" + uninitializedType.u2newInstructionOffset + "]");
}
public void visitUninitializedThisType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedThisType uninitializedThisType)
{
ps.print("[u:this]");
}
// Implementations for LineNumberInfoVisitor.
public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
{
println("[" + lineNumberInfo.u2startPC + "] -> line " +
lineNumberInfo.u2lineNumber);
}
// Implementations for ParameterInfoVisitor.
public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
{
println("p" + parameterIndex + ": Access flags: 0x" + Integer.toHexString(parameterInfo.u2accessFlags) + " = " +
ClassUtil.externalParameterAccessFlags(parameterInfo.u2accessFlags) + " [" +
(parameterInfo.u2nameIndex == 0 ? "" : parameterInfo.getName(clazz)) + "]");
}
// Implementations for LocalVariableInfoVisitor.
public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
{
println("v" + localVariableInfo.u2index + ": " +
localVariableInfo.u2startPC + " -> " +
(localVariableInfo.u2startPC + localVariableInfo.u2length) + " [" +
localVariableInfo.getDescriptor(clazz) + " " +
localVariableInfo.getName(clazz) + "]");
}
// Implementations for LocalVariableTypeInfoVisitor.
public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
{
println("v" + localVariableTypeInfo.u2index + ": " +
localVariableTypeInfo.u2startPC + " -> " +
(localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length) + " [" +
localVariableTypeInfo.getSignature(clazz) + " " +
localVariableTypeInfo.getName(clazz) + "]");
}
// Implementations for AnnotationVisitor.
public void visitAnnotation(Clazz clazz, Annotation annotation)
{
println(visitorInfo(annotation) +
" Annotation [" + annotation.getType(clazz) + "]:");
indent();
annotation.elementValuesAccept(clazz, this);
outdent();
}
// Implementations for TypeAnnotationVisitor.
public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation)
{
println(visitorInfo(typeAnnotation) +
" Type annotation [" + typeAnnotation.getType(clazz) + "]:");
indent();
typeAnnotation.targetInfoAccept(clazz, this);
println("Type path (count = " + typeAnnotation.typePath.length + "):");
indent();
typeAnnotation.typePathInfosAccept(clazz, this);
outdent();
typeAnnotation.elementValuesAccept(clazz, this);
outdent();
}
// Implementations for TargetInfoVisitor.
public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(typeParameterTargetInfo.u1targetType) + "): Parameter #" +
typeParameterTargetInfo.u1typeParameterIndex);
}
public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(superTypeTargetInfo.u1targetType) + "): " +
(superTypeTargetInfo.u2superTypeIndex == 0xffff ?
"super class" :
"interface #" + superTypeTargetInfo.u2superTypeIndex));
}
public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(typeParameterBoundTargetInfo.u1targetType) + "): parameter #" +
typeParameterBoundTargetInfo.u1typeParameterIndex + ", bound #" + typeParameterBoundTargetInfo.u1boundIndex);
}
public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(emptyTargetInfo.u1targetType) + ")");
}
public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(formalParameterTargetInfo.u1targetType) + "): formal parameter #" +
formalParameterTargetInfo.u1formalParameterIndex);
}
public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(throwsTargetInfo.u1targetType) + "): throws #" +
throwsTargetInfo.u2throwsTypeIndex);
}
public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(localVariableTargetInfo.u1targetType) + "): local variables (count = " +
localVariableTargetInfo.u2tableLength + ")");
indent();
localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this);
outdent();
}
public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(catchTargetInfo.u1targetType) + "): catch #" +
catchTargetInfo.u2exceptionTableIndex);
}
public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(offsetTargetInfo.u1targetType) + "): offset " +
offsetTargetInfo.u2offset);
}
public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo)
{
println("Target (type = 0x" + Integer.toHexString(typeArgumentTargetInfo.u1targetType) + "): offset " +
typeArgumentTargetInfo.u2offset + ", type argument " +
typeArgumentTargetInfo.u1typeArgumentIndex);
}
// Implementations for TypePathInfoVisitor.
public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo)
{
println("kind = " +
typePathInfo.u1typePathKind + ", argument index = " +
typePathInfo.u1typeArgumentIndex);
}
// Implementations for LocalVariableTargetElementVisitor.
public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement)
{
println("v" +
localVariableTargetElement.u2index + ": " +
localVariableTargetElement.u2startPC + " -> " +
(localVariableTargetElement.u2startPC + localVariableTargetElement.u2length));
}
// Implementations for ElementValueVisitor.
public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
{
println(visitorInfo(constantElementValue) +
" Constant element value [" +
(constantElementValue.u2elementNameIndex == 0 ? "(default)" :
constantElementValue.getMethodName(clazz)) + " '" +
constantElementValue.u1tag + "']");
indent();
clazz.constantPoolEntryAccept(constantElementValue.u2constantValueIndex, this);
outdent();
}
public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
{
println(visitorInfo(enumConstantElementValue) +
" Enum constant element value [" +
(enumConstantElementValue.u2elementNameIndex == 0 ? "(default)" :
enumConstantElementValue.getMethodName(clazz)) + ", " +
enumConstantElementValue.getTypeName(clazz) + ", " +
enumConstantElementValue.getConstantName(clazz) + "]");
}
public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
{
println(visitorInfo(classElementValue) +
" Class element value [" +
(classElementValue.u2elementNameIndex == 0 ? "(default)" :
classElementValue.getMethodName(clazz)) + ", " +
classElementValue.getClassName(clazz) + "]");
}
public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
{
println(visitorInfo(annotationElementValue) +
" Annotation element value [" +
(annotationElementValue.u2elementNameIndex == 0 ? "(default)" :
annotationElementValue.getMethodName(clazz)) + "]:");
indent();
annotationElementValue.annotationAccept(clazz, this);
outdent();
}
public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
{
println(visitorInfo(arrayElementValue) +
" Array element value [" +
(arrayElementValue.u2elementNameIndex == 0 ? "(default)" :
arrayElementValue.getMethodName(clazz)) + "]:");
indent();
arrayElementValue.elementValuesAccept(clazz, annotation, this);
outdent();
}
// Small utility methods.
private void indent()
{
indentation++;
}
private void outdent()
{
indentation--;
}
private void println(String string)
{
print(string);
println();
}
private void print(String string)
{
for (int index = 0; index < indentation; index++)
{
ps.print(INDENTATION);
}
ps.print(string);
}
private void println()
{
ps.println();
}
private String visitorInfo(VisitorAccepter visitorAccepter)
{
return visitorAccepter.getVisitorInfo() == null ? "-" : "+";
}
}