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