Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. package javassist.bytecode;
  2. import java.util.Iterator;
  3. import java.util.List;
  4. import java.util.regex.Pattern;
  5. import java.util.regex.Matcher;
  6. import java.io.ByteArrayOutputStream;
  7. import java.io.IOException;
  8. import java.io.PrintStream;
  9. import java.lang.reflect.Method;
  10. import javassist.ClassPool;
  11. import javassist.CtClass;
  12. import javassist.CtMethod;
  13. import javassist.CtNewMethod;
  14. import javassist.JvstTest;
  15. import javassist.Loader;
  16. import javassist.bytecode.stackmap.MapMaker;
  17. import javassist.bytecode.stackmap.TypeData;
  18. import junit.framework.TestCase;
  19. public class StackMapTest extends TestCase {
  20. public static final String PATH = JvstTest.PATH;
  21. private ClassPool loader, dloader;
  22. private Loader cloader;
  23. public StackMapTest(String name) { super(name); }
  24. protected void setUp() throws Exception {
  25. loader = ClassPool.getDefault();
  26. dloader = new ClassPool(null);
  27. dloader.appendSystemPath();
  28. dloader.insertClassPath(".");
  29. cloader = new Loader(dloader);
  30. }
  31. protected Object make(String name) throws Exception {
  32. return cloader.loadClass(name).newInstance();
  33. }
  34. protected int invoke(Object target, String method) throws Exception {
  35. Method m = target.getClass().getMethod(method, new Class[0]);
  36. Object res = m.invoke(target, new Object[0]);
  37. return ((Integer)res).intValue();
  38. }
  39. protected static void rebuildStackMaps(CtClass cc) throws BadBytecode, IOException {
  40. ClassPool cp = cc.getClassPool();
  41. Iterator it = cc.getClassFile().getMethods().iterator();
  42. while (it.hasNext()) {
  43. MethodInfo minfo = (MethodInfo)it.next();
  44. rebuildStackMap(cc, cp, minfo);
  45. }
  46. }
  47. protected static void rebuildStackMap(CtClass cc, ClassPool cp, MethodInfo minfo) throws BadBytecode, IOException {
  48. CodeAttribute ca = minfo.getCodeAttribute();
  49. if (ca != null) {
  50. StackMapTable smt = (StackMapTable)ca.getAttribute(StackMapTable.tag);
  51. if (smt != null) {
  52. String data = readSmt(smt);
  53. StackMapTable smt2 = MapMaker.make(cp, minfo);
  54. String data2 = readSmt(smt2);
  55. try {
  56. assertEquals(cc.getName() + ":" + minfo.getName() + ":" + minfo.getDescriptor(),
  57. data, data2);
  58. }
  59. catch (junit.framework.ComparisonFailure e) {
  60. System.out.println("*** " + cc.getName() + ":" + minfo.getName() + ":" + minfo.getDescriptor());
  61. smt.println(System.out);
  62. System.out.println("---");
  63. smt2.println(System.out);
  64. }
  65. }
  66. }
  67. }
  68. protected static void rebuildStackMaps2(CtClass cc) throws BadBytecode {
  69. ClassPool cp = cc.getClassPool();
  70. Iterator it = cc.getClassFile().getMethods().iterator();
  71. while (it.hasNext()) {
  72. MethodInfo minfo = (MethodInfo)it.next();
  73. minfo.rebuildStackMap(cp);
  74. }
  75. }
  76. protected static String readSmt(StackMapTable smt) throws BadBytecode, IOException {
  77. if (smt == null)
  78. return "";
  79. ByteArrayOutputStream out = new ByteArrayOutputStream();
  80. PrintStream pout = new PrintStream(out);
  81. smt.println(pout);
  82. pout.close();
  83. return out.toString();
  84. }
  85. public static void main(String[] args) throws Exception {
  86. if (args.length == 2 && args[0].equals("-c")) {
  87. CtClass cc = ClassPool.getDefault().get(args[0].replace('/', '.'));
  88. rebuildStackMaps(cc);
  89. }
  90. else {
  91. for (int i = 0; i < args.length; i++) {
  92. CtClass cc = ClassPool.getDefault().get(getClassName(args[i]));
  93. System.out.println(cc.getName());
  94. rebuildStackMaps2(cc);
  95. cc.writeFile("rebuild");
  96. }
  97. }
  98. }
  99. public static String getClassName(String fileName) {
  100. Matcher m = Pattern.compile("(.*)\\.class").matcher(fileName);
  101. if (m.matches())
  102. return m.group(1).replace('/', '.');
  103. else
  104. return fileName;
  105. }
  106. public void testCommonSuper() throws Exception {
  107. CtClass type = loader.get("javassist.CtClassType[]");
  108. CtClass base = loader.get("javassist.CtClass[]");
  109. CtClass array = loader.get("javassist.CtArray[]");
  110. CtClass array2 = loader.get("javassist.CtArray[][]");
  111. CtClass str = loader.get("java.lang.String[]");
  112. CtClass strObj = loader.get("java.lang.String");
  113. CtClass obj = loader.get("java.lang.Object[]");
  114. CtClass objObj = loader.get("java.lang.Object");
  115. assertEquals(base, TypeData.commonSuperClassEx(type, base));
  116. assertEquals(base, TypeData.commonSuperClassEx(base, type));
  117. assertEquals(base, TypeData.commonSuperClassEx(array, type));
  118. assertEquals(obj, TypeData.commonSuperClassEx(base, str));
  119. assertEquals(objObj, TypeData.commonSuperClassEx(strObj, str));
  120. assertEquals(obj, TypeData.commonSuperClassEx(array, array2));
  121. assertEquals(obj, TypeData.commonSuperClassEx(base, array2));
  122. }
  123. public void testRebuild() throws Exception {
  124. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T1");
  125. rebuildStackMaps2(cc);
  126. //Class c = cc.toClass();
  127. //Object t1 = c.newInstance();
  128. cc.writeFile();
  129. Object t1 = make(cc.getName());
  130. assertEquals(3, invoke(t1, "test"));
  131. }
  132. public static interface Intf {
  133. int foo();
  134. }
  135. public static class C1 implements Intf {
  136. public int foo() { return 0; }
  137. }
  138. public static class C2 implements Intf {
  139. public int foo() { return 3; }
  140. }
  141. public static class T1 {
  142. public int test() {
  143. return foo(-1);
  144. }
  145. public int foo(int i) {
  146. Intf obj;
  147. if (i > 0)
  148. obj = new C1();
  149. else
  150. obj = new C2();
  151. return obj.foo();
  152. }
  153. }
  154. public void testRebuild2() throws Exception {
  155. CtClass cc = loader.get("javassist.bytecode.StackMapTest$C3");
  156. rebuildStackMaps2(cc);
  157. cc.writeFile();
  158. Object t1 = make(cc.getName());
  159. assertEquals(7, invoke(t1, "test"));
  160. }
  161. public static class C3 {
  162. int value;
  163. public C3(int i) {
  164. value = i;
  165. }
  166. public C3(boolean b) {
  167. this(b ? 7 : 10);
  168. }
  169. public C3() { this(true); }
  170. public int test() { return value; }
  171. }
  172. public void testRebuild3() throws Exception {
  173. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T3");
  174. rebuildStackMaps2(cc);
  175. cc.writeFile();
  176. Object t1 = make(cc.getName());
  177. assertEquals(1100, invoke(t1, "test"));
  178. }
  179. public static interface Intf2 {
  180. int bar();
  181. }
  182. public static class D1 extends C1 implements Intf2 {
  183. public int bar() { return 10; }
  184. }
  185. public static class D2 extends C1 implements Intf2 {
  186. public int bar() { return 100; }
  187. }
  188. public static class T3 {
  189. public int bar(Intf2 i) { return 1000; }
  190. public int test() {
  191. return foo(-1);
  192. }
  193. public int foo(int i) {
  194. Intf2 obj;
  195. if (i > 0)
  196. obj = new D1();
  197. else
  198. obj = new D2();
  199. System.out.println(obj.toString());
  200. return obj.bar() + bar(obj);
  201. }
  202. }
  203. public void testRebuildArray() throws Exception {
  204. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T4");
  205. rebuildStackMaps2(cc);
  206. cc.writeFile();
  207. Object t1 = make(cc.getName());
  208. assertEquals(30, invoke(t1, "test"));
  209. }
  210. public static class T4 {
  211. public int test() {
  212. return foo(3) + foo2(3) + foo3(3) + foo4(3);
  213. }
  214. public int foo(int i) {
  215. C1[] a;
  216. if (i > 0)
  217. a = new D1[1];
  218. else
  219. a = new D2[1];
  220. if (i > 0)
  221. a[0] = new D1();
  222. else
  223. a[0] = new D2();
  224. return a[0].foo();
  225. }
  226. public int foo2(int i) {
  227. Intf2[] a;
  228. if (i > 0)
  229. a = new D1[1];
  230. else
  231. a = new D2[1];
  232. if (i > 0)
  233. a[0] = new D1();
  234. else
  235. a[0] = new D2();
  236. return a[0].bar();
  237. }
  238. public int foo3(int i) {
  239. Intf2[] a = null;
  240. if (i > 0)
  241. a = new D1[1];
  242. a[0] = new D1();
  243. return a[0].bar();
  244. }
  245. public int foo4(int i) {
  246. Intf2[] a = new Intf2[1];
  247. if (i > 0)
  248. a[0] = new D1();
  249. return a[0].bar();
  250. }
  251. }
  252. public void testRebuildConstructor() throws Exception {
  253. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T5");
  254. rebuildStackMaps2(cc);
  255. cc.writeFile();
  256. Object t1 = make(cc.getName());
  257. assertEquals(122, invoke(t1, "test"));
  258. }
  259. public static class T5 {
  260. int count;
  261. public T5() { count = 0; }
  262. public T5(int k) {
  263. if (k > 0) count = 10;
  264. else count = 100;
  265. count++;
  266. }
  267. public T5(double d) {
  268. this(d > 0.0 ? 1 : -1);
  269. if (d > 1.0) count += 10;
  270. else count += 100;
  271. count++;
  272. }
  273. public int test() {
  274. return new T5(3).count + new T5(1.0).count;
  275. }
  276. }
  277. public void testRebuildConstructor2() throws Exception {
  278. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T6");
  279. rebuildStackMaps2(cc);
  280. cc.writeFile();
  281. Object t1 = make(cc.getName());
  282. assertEquals(101, invoke(t1, "test2"));
  283. }
  284. public static class T6 {
  285. public int test2() {
  286. T5 t0 = new T5();
  287. T5 t = new T5(t0.count > 0 ? (new T5(t0.count > 0 ? 1 : -1).count) : -1);
  288. if (t0.count > 0)
  289. t.count += 1000;
  290. return t.count;
  291. }
  292. }
  293. public void tstCtClassType() throws Exception {
  294. ClassPool cp = ClassPool.getDefault();
  295. CtClass cc = cp.get("javassist.CtClassType");
  296. MethodInfo minfo = getMethodInfo(cc.getClassFile(), "getFields", "(Ljava/util/ArrayList;Ljavassist/CtClass;)V");
  297. rebuildStackMap(cc, cp, minfo);
  298. }
  299. MethodInfo getMethodInfo(ClassFile cf, String name, String desc) {
  300. List list = cf.getMethods();
  301. Iterator it = list.iterator();
  302. while (it.hasNext()) {
  303. MethodInfo mi = (MethodInfo)it.next();
  304. if (mi.getName().equals(name) && mi.getDescriptor().equals(desc))
  305. return mi;
  306. }
  307. return null;
  308. }
  309. }