You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FramePrinter.java 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. import java.io.PrintStream;
  18. import javassist.CtClass;
  19. import javassist.CtMethod;
  20. import javassist.Modifier;
  21. import javassist.NotFoundException;
  22. import javassist.bytecode.BadBytecode;
  23. import javassist.bytecode.CodeAttribute;
  24. import javassist.bytecode.CodeIterator;
  25. import javassist.bytecode.ConstPool;
  26. import javassist.bytecode.Descriptor;
  27. import javassist.bytecode.InstructionPrinter;
  28. import javassist.bytecode.MethodInfo;
  29. /**
  30. * A utility class for printing a merged view of the frame state and the
  31. * instructions of a method.
  32. *
  33. * @author Jason T. Greene
  34. */
  35. public final class FramePrinter {
  36. private final PrintStream stream;
  37. /**
  38. * Constructs a bytecode printer.
  39. */
  40. public FramePrinter(PrintStream stream) {
  41. this.stream = stream;
  42. }
  43. /**
  44. * Prints all the methods declared in the given class.
  45. */
  46. public static void print(CtClass clazz, PrintStream stream) {
  47. (new FramePrinter(stream)).print(clazz);
  48. }
  49. /**
  50. * Prints all the methods declared in the given class.
  51. */
  52. public void print(CtClass clazz) {
  53. CtMethod[] methods = clazz.getDeclaredMethods();
  54. for (int i = 0; i < methods.length; i++) {
  55. print(methods[i]);
  56. }
  57. }
  58. private String getMethodString(CtMethod method) {
  59. try {
  60. return Modifier.toString(method.getModifiers()) + " "
  61. + method.getReturnType().getName() + " " + method.getName()
  62. + Descriptor.toString(method.getSignature()) + ";";
  63. } catch (NotFoundException e) {
  64. throw new RuntimeException(e);
  65. }
  66. }
  67. /**
  68. * Prints the instructions and the frame states of the given method.
  69. */
  70. public void print(CtMethod method) {
  71. stream.println("\n" + getMethodString(method));
  72. MethodInfo info = method.getMethodInfo2();
  73. ConstPool pool = info.getConstPool();
  74. CodeAttribute code = info.getCodeAttribute();
  75. if (code == null)
  76. return;
  77. Frame[] frames;
  78. try {
  79. frames = (new Analyzer()).analyze(method.getDeclaringClass(), info);
  80. } catch (BadBytecode e) {
  81. throw new RuntimeException(e);
  82. }
  83. int spacing = String.valueOf(code.getCodeLength()).length();
  84. CodeIterator iterator = code.iterator();
  85. while (iterator.hasNext()) {
  86. int pos;
  87. try {
  88. pos = iterator.next();
  89. } catch (BadBytecode e) {
  90. throw new RuntimeException(e);
  91. }
  92. stream.println(pos + ": " + InstructionPrinter.instructionString(iterator, pos, pool));
  93. addSpacing(spacing + 3);
  94. Frame frame = frames[pos];
  95. if (frame == null) {
  96. stream.println("--DEAD CODE--");
  97. continue;
  98. }
  99. printStack(frame);
  100. addSpacing(spacing + 3);
  101. printLocals(frame);
  102. }
  103. }
  104. private void printStack(Frame frame) {
  105. stream.print("stack [");
  106. int top = frame.getTopIndex();
  107. for (int i = 0; i <= top; i++) {
  108. if (i > 0)
  109. stream.print(", ");
  110. Type type = frame.getStack(i);
  111. stream.print(type);
  112. }
  113. stream.println("]");
  114. }
  115. private void printLocals(Frame frame) {
  116. stream.print("locals [");
  117. int length = frame.localsLength();
  118. for (int i = 0; i < length; i++) {
  119. if (i > 0)
  120. stream.print(", ");
  121. Type type = frame.getLocal(i);
  122. stream.print(type == null ? "empty" : type.toString());
  123. }
  124. stream.println("]");
  125. }
  126. private void addSpacing(int count) {
  127. while (count-- > 0)
  128. stream.print(' ');
  129. }
  130. }