aboutsummaryrefslogtreecommitdiff
path: root/src/main/javassist/bytecode/analysis/FramePrinter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/bytecode/analysis/FramePrinter.java')
-rw-r--r--src/main/javassist/bytecode/analysis/FramePrinter.java147
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(' ');
+ }
+}