• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2007 Shigeru Chiba, and others. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License.  Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */
15 package javassist.bytecode.analysis;
16 
17 import java.io.PrintStream;
18 
19 import javassist.CtClass;
20 import javassist.CtMethod;
21 import javassist.Modifier;
22 import javassist.NotFoundException;
23 import javassist.bytecode.BadBytecode;
24 import javassist.bytecode.CodeAttribute;
25 import javassist.bytecode.CodeIterator;
26 import javassist.bytecode.ConstPool;
27 import javassist.bytecode.Descriptor;
28 import javassist.bytecode.InstructionPrinter;
29 import javassist.bytecode.MethodInfo;
30 
31 /**
32  * A utility class for printing a merged view of the frame state and the
33  * instructions of a method.
34  *
35  * @author Jason T. Greene
36  */
37 public final class FramePrinter {
38     private final PrintStream stream;
39 
40     /**
41      * Constructs a bytecode printer.
42      */
FramePrinter(PrintStream stream)43     public FramePrinter(PrintStream stream) {
44         this.stream = stream;
45     }
46 
47     /**
48      * Prints all the methods declared in the given class.
49      */
print(CtClass clazz, PrintStream stream)50     public static void print(CtClass clazz, PrintStream stream) {
51         (new FramePrinter(stream)).print(clazz);
52     }
53 
54     /**
55      * Prints all the methods declared in the given class.
56      */
print(CtClass clazz)57     public void print(CtClass clazz) {
58         CtMethod[] methods = clazz.getDeclaredMethods();
59         for (int i = 0; i < methods.length; i++) {
60             print(methods[i]);
61         }
62     }
63 
getMethodString(CtMethod method)64     private String getMethodString(CtMethod method) {
65         try {
66             return Modifier.toString(method.getModifiers()) + " "
67                     + method.getReturnType().getName() + " " + method.getName()
68                     + Descriptor.toString(method.getSignature()) + ";";
69         } catch (NotFoundException e) {
70             throw new RuntimeException(e);
71         }
72     }
73 
74     /**
75      * Prints the instructions and the frame states of the given method.
76      */
print(CtMethod method)77     public void print(CtMethod method) {
78         stream.println("\n" + getMethodString(method));
79         MethodInfo info = method.getMethodInfo2();
80         ConstPool pool = info.getConstPool();
81         CodeAttribute code = info.getCodeAttribute();
82         if (code == null)
83             return;
84 
85         Frame[] frames;
86         try {
87             frames = (new Analyzer()).analyze(method.getDeclaringClass(), info);
88         } catch (BadBytecode e) {
89             throw new RuntimeException(e);
90         }
91 
92         int spacing = String.valueOf(code.getCodeLength()).length();
93 
94         CodeIterator iterator = code.iterator();
95         while (iterator.hasNext()) {
96             int pos;
97             try {
98                 pos = iterator.next();
99             } catch (BadBytecode e) {
100                 throw new RuntimeException(e);
101             }
102 
103             stream.println(pos + ": " + InstructionPrinter.instructionString(iterator, pos, pool));
104 
105             addSpacing(spacing + 3);
106             Frame frame = frames[pos];
107             if (frame == null) {
108                 stream.println("--DEAD CODE--");
109                 continue;
110             }
111             printStack(frame);
112 
113             addSpacing(spacing + 3);
114             printLocals(frame);
115         }
116 
117     }
118 
printStack(Frame frame)119     private void printStack(Frame frame) {
120         stream.print("stack [");
121         int top = frame.getTopIndex();
122         for (int i = 0; i <= top; i++) {
123             if (i > 0)
124                 stream.print(", ");
125             Type type = frame.getStack(i);
126             stream.print(type);
127         }
128         stream.println("]");
129     }
130 
printLocals(Frame frame)131     private void printLocals(Frame frame) {
132         stream.print("locals [");
133         int length = frame.localsLength();
134         for (int i = 0; i < length; i++) {
135             if (i > 0)
136                 stream.print(", ");
137             Type type = frame.getLocal(i);
138             stream.print(type == null ? "empty" : type.toString());
139         }
140         stream.println("]");
141     }
142 
addSpacing(int count)143     private void addSpacing(int count) {
144         while (count-- > 0)
145             stream.print(' ');
146     }
147 }
148