diff options
Diffstat (limited to 'src/main/javassist/bytecode/analysis/FramePrinter.java')
-rw-r--r-- | src/main/javassist/bytecode/analysis/FramePrinter.java | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/main/javassist/bytecode/analysis/FramePrinter.java b/src/main/javassist/bytecode/analysis/FramePrinter.java new file mode 100644 index 0000000..fc99cd3 --- /dev/null +++ b/src/main/javassist/bytecode/analysis/FramePrinter.java @@ -0,0 +1,147 @@ +/* + * Javassist, a Java-bytecode translator toolkit. + * Copyright (C) 1999-2007 Shigeru Chiba, and others. All Rights Reserved. + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. Alternatively, the contents of this file may be used under + * the terms of the GNU Lesser General Public License Version 2.1 or later. + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + */ +package javassist.bytecode.analysis; + +import java.io.PrintStream; + +import javassist.CtClass; +import javassist.CtMethod; +import javassist.Modifier; +import javassist.NotFoundException; +import javassist.bytecode.BadBytecode; +import javassist.bytecode.CodeAttribute; +import javassist.bytecode.CodeIterator; +import javassist.bytecode.ConstPool; +import javassist.bytecode.Descriptor; +import javassist.bytecode.InstructionPrinter; +import javassist.bytecode.MethodInfo; + +/** + * A utility class for printing a merged view of the frame state and the + * instructions of a method. + * + * @author Jason T. Greene + */ +public final class FramePrinter { + private final PrintStream stream; + + /** + * Constructs a bytecode printer. + */ + public FramePrinter(PrintStream stream) { + this.stream = stream; + } + + /** + * Prints all the methods declared in the given class. + */ + public static void print(CtClass clazz, PrintStream stream) { + (new FramePrinter(stream)).print(clazz); + } + + /** + * Prints all the methods declared in the given class. + */ + public void print(CtClass clazz) { + CtMethod[] methods = clazz.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + print(methods[i]); + } + } + + private String getMethodString(CtMethod method) { + try { + return Modifier.toString(method.getModifiers()) + " " + + method.getReturnType().getName() + " " + method.getName() + + Descriptor.toString(method.getSignature()) + ";"; + } catch (NotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Prints the instructions and the frame states of the given method. + */ + public void print(CtMethod method) { + stream.println("\n" + getMethodString(method)); + MethodInfo info = method.getMethodInfo2(); + ConstPool pool = info.getConstPool(); + CodeAttribute code = info.getCodeAttribute(); + if (code == null) + return; + + Frame[] frames; + try { + frames = (new Analyzer()).analyze(method.getDeclaringClass(), info); + } catch (BadBytecode e) { + throw new RuntimeException(e); + } + + int spacing = String.valueOf(code.getCodeLength()).length(); + + CodeIterator iterator = code.iterator(); + while (iterator.hasNext()) { + int pos; + try { + pos = iterator.next(); + } catch (BadBytecode e) { + throw new RuntimeException(e); + } + + stream.println(pos + ": " + InstructionPrinter.instructionString(iterator, pos, pool)); + + addSpacing(spacing + 3); + Frame frame = frames[pos]; + if (frame == null) { + stream.println("--DEAD CODE--"); + continue; + } + printStack(frame); + + addSpacing(spacing + 3); + printLocals(frame); + } + + } + + private void printStack(Frame frame) { + stream.print("stack ["); + int top = frame.getTopIndex(); + for (int i = 0; i <= top; i++) { + if (i > 0) + stream.print(", "); + Type type = frame.getStack(i); + stream.print(type); + } + stream.println("]"); + } + + private void printLocals(Frame frame) { + stream.print("locals ["); + int length = frame.localsLength(); + for (int i = 0; i < length; i++) { + if (i > 0) + stream.print(", "); + Type type = frame.getLocal(i); + stream.print(type == null ? "empty" : type.toString()); + } + stream.println("]"); + } + + private void addSpacing(int count) { + while (count-- > 0) + stream.print(' '); + } +} |