| /* |
| * ProGuard -- shrinking, optimization, obfuscation, and preverification |
| * of Java bytecode. |
| * |
| * Copyright (c) 2002-2013 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.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, |
| LocalVariableInfoVisitor, |
| LocalVariableTypeInfoVisitor, |
| AnnotationVisitor, |
| 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.INTERNAL_ACC_ANNOTATTION) != 0 ? "@ " : "") + |
| ClassUtil.externalClassAccessFlags(programClass.u2accessFlags) + |
| ((programClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ENUM) != 0 ? "enum " : |
| (programClass.u2accessFlags & ClassConstants.INTERNAL_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.INTERNAL_ACC_ANNOTATTION) != 0 ? "@ " : "") + |
| ClassUtil.externalClassAccessFlags(libraryClass.u2accessFlags) + |
| ((libraryClass.u2accessFlags & ClassConstants.INTERNAL_ACC_ENUM) != 0 ? "enum " : |
| (libraryClass.u2accessFlags & ClassConstants.INTERNAL_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 [" + |
| clazz.getString(stringConstant.u2stringIndex) + "]"); |
| } |
| |
| |
| 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 [" + |
| clazz.getString(classConstant.u2nameIndex) + "]"); |
| } |
| |
| |
| public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) |
| { |
| println(visitorInfo(methodTypeConstant) + " MethodType [" + |
| clazz.getString(methodTypeConstant.u2descriptorIndex) + "]"); |
| } |
| |
| |
| public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) |
| { |
| println(visitorInfo(nameAndTypeConstant) + " NameAndType [" + |
| clazz.getString(nameAndTypeConstant.u2nameIndex) + " " + |
| clazz.getString(nameAndTypeConstant.u2descriptorIndex) + "]"); |
| } |
| |
| |
| // 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 (" + clazz.getString(unknownAttribute.u2attributeNameIndex) + ")"); |
| } |
| |
| |
| 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 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.u2parametersCount + "):"); |
| |
| 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.u2parametersCount + "):"); |
| |
| indent(); |
| runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, method, 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 LocalVariableInfoVisitor. |
| |
| public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) |
| { |
| println("v" + localVariableInfo.u2index + ": " + |
| localVariableInfo.u2startPC + " -> " + |
| (localVariableInfo.u2startPC + localVariableInfo.u2length) + " [" + |
| clazz.getString(localVariableInfo.u2descriptorIndex) + " " + |
| clazz.getString(localVariableInfo.u2nameIndex) + "]"); |
| } |
| |
| |
| // Implementations for LocalVariableTypeInfoVisitor. |
| |
| public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) |
| { |
| println("v" + localVariableTypeInfo.u2index + ": " + |
| localVariableTypeInfo.u2startPC + " -> " + |
| (localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length) + " [" + |
| clazz.getString(localVariableTypeInfo.u2signatureIndex) + " " + |
| clazz.getString(localVariableTypeInfo.u2nameIndex) + "]"); |
| } |
| |
| |
| // Implementations for AnnotationVisitor. |
| |
| public void visitAnnotation(Clazz clazz, Annotation annotation) |
| { |
| println(visitorInfo(annotation) + |
| " Annotation [" + clazz.getString(annotation.u2typeIndex) + "]:"); |
| |
| indent(); |
| annotation.elementValuesAccept(clazz, this); |
| outdent(); |
| } |
| |
| |
| // Implementations for ElementValueVisitor. |
| |
| public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) |
| { |
| println(visitorInfo(constantElementValue) + |
| " Constant element value [" + |
| (constantElementValue.u2elementNameIndex == 0 ? "(default)" : |
| clazz.getString(constantElementValue.u2elementNameIndex)) + " '" + |
| 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)" : |
| clazz.getString(enumConstantElementValue.u2elementNameIndex)) + ", " + |
| clazz.getString(enumConstantElementValue.u2typeNameIndex) + ", " + |
| clazz.getString(enumConstantElementValue.u2constantNameIndex) + "]"); |
| } |
| |
| |
| public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) |
| { |
| println(visitorInfo(classElementValue) + |
| " Class element value [" + |
| (classElementValue.u2elementNameIndex == 0 ? "(default)" : |
| clazz.getString(classElementValue.u2elementNameIndex)) + ", " + |
| clazz.getString(classElementValue.u2classInfoIndex) + "]"); |
| } |
| |
| |
| public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) |
| { |
| println(visitorInfo(annotationElementValue) + |
| " Annotation element value [" + |
| (annotationElementValue.u2elementNameIndex == 0 ? "(default)" : |
| clazz.getString(annotationElementValue.u2elementNameIndex)) + "]:"); |
| |
| 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)" : |
| clazz.getString(arrayElementValue.u2elementNameIndex)) + "]:"); |
| |
| 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 ? "-" : "+"; |
| } |
| } |