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.

StackMapTest.java 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  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.CodeConverter;
  12. import javassist.CtClass;
  13. import javassist.CtConstructor;
  14. import javassist.CtMethod;
  15. import javassist.CtNewConstructor;
  16. import javassist.CtNewMethod;
  17. import javassist.JvstTest;
  18. import javassist.Loader;
  19. import javassist.bytecode.stackmap.MapMaker;
  20. import javassist.bytecode.stackmap.TypeData;
  21. import junit.framework.TestCase;
  22. @SuppressWarnings({"rawtypes","unused"})
  23. public class StackMapTest extends TestCase {
  24. public static final String PATH = JvstTest.PATH;
  25. private ClassPool loader, dloader;
  26. private Loader cloader;
  27. public StackMapTest(String name) { super(name); }
  28. protected void setUp() throws Exception {
  29. loader = ClassPool.getDefault();
  30. dloader = new ClassPool(null);
  31. dloader.appendSystemPath();
  32. dloader.insertClassPath(".");
  33. cloader = new Loader(dloader);
  34. }
  35. protected Object make(String name) throws Exception {
  36. return cloader.loadClass(name).getConstructor().newInstance();
  37. }
  38. protected int invoke(Object target, String method) throws Exception {
  39. Method m = target.getClass().getMethod(method, new Class[0]);
  40. Object res = m.invoke(target, new Object[0]);
  41. return ((Integer)res).intValue();
  42. }
  43. protected static void rebuildStackMaps(CtClass cc) throws BadBytecode, IOException {
  44. ClassPool cp = cc.getClassPool();
  45. Iterator it = cc.getClassFile().getMethods().iterator();
  46. while (it.hasNext()) {
  47. MethodInfo minfo = (MethodInfo)it.next();
  48. rebuildStackMap(cc, cp, minfo);
  49. }
  50. }
  51. protected static void rebuildStackMap(CtClass cc, ClassPool cp, MethodInfo minfo) throws BadBytecode, IOException {
  52. CodeAttribute ca = minfo.getCodeAttribute();
  53. if (ca != null) {
  54. StackMapTable smt = (StackMapTable)ca.getAttribute(StackMapTable.tag);
  55. if (smt != null) {
  56. String data = readSmt(smt);
  57. StackMapTable smt2 = MapMaker.make(cp, minfo);
  58. String data2 = readSmt(smt2);
  59. try {
  60. assertEquals(cc.getName() + ":" + minfo.getName() + ":" + minfo.getDescriptor(),
  61. data, data2);
  62. }
  63. catch (junit.framework.ComparisonFailure e) {
  64. System.out.println("*** " + cc.getName() + ":" + minfo.getName() + ":" + minfo.getDescriptor());
  65. smt.println(System.out);
  66. System.out.println("---");
  67. smt2.println(System.out);
  68. }
  69. }
  70. }
  71. }
  72. protected static void rebuildStackMaps2(CtClass cc) throws BadBytecode {
  73. ClassPool cp = cc.getClassPool();
  74. Iterator it = cc.getClassFile().getMethods().iterator();
  75. while (it.hasNext()) {
  76. MethodInfo minfo = (MethodInfo)it.next();
  77. minfo.rebuildStackMap(cp);
  78. }
  79. }
  80. protected static String readSmt(StackMapTable smt) throws BadBytecode, IOException {
  81. if (smt == null)
  82. return "";
  83. ByteArrayOutputStream out = new ByteArrayOutputStream();
  84. PrintStream pout = new PrintStream(out);
  85. smt.println(pout);
  86. pout.close();
  87. return out.toString();
  88. }
  89. public static void main(String[] args) throws Exception {
  90. if (args.length == 2 && args[0].equals("-c")) {
  91. CtClass cc = ClassPool.getDefault().get(args[0].replace('/', '.'));
  92. rebuildStackMaps(cc);
  93. }
  94. else {
  95. for (int i = 0; i < args.length; i++) {
  96. CtClass cc = ClassPool.getDefault().get(getClassName(args[i]));
  97. System.out.println(cc.getName());
  98. rebuildStackMaps2(cc);
  99. cc.writeFile("rebuild");
  100. }
  101. }
  102. }
  103. public static String getClassName(String fileName) {
  104. Matcher m = Pattern.compile("(.*)\\.class").matcher(fileName);
  105. if (m.matches())
  106. return m.group(1).replace('/', '.');
  107. else
  108. return fileName;
  109. }
  110. public void testCommonSuper() throws Exception {
  111. CtClass type = loader.get("javassist.CtClassType[]");
  112. CtClass base = loader.get("javassist.CtClass[]");
  113. CtClass array = loader.get("javassist.CtArray[]");
  114. CtClass array2 = loader.get("javassist.CtArray[][]");
  115. CtClass str = loader.get("java.lang.String[]");
  116. CtClass strObj = loader.get("java.lang.String");
  117. CtClass obj = loader.get("java.lang.Object[]");
  118. CtClass objObj = loader.get("java.lang.Object");
  119. assertEquals(base, TypeData.commonSuperClassEx(type, base));
  120. assertEquals(base, TypeData.commonSuperClassEx(base, type));
  121. assertEquals(base, TypeData.commonSuperClassEx(array, type));
  122. assertEquals(obj, TypeData.commonSuperClassEx(base, str));
  123. assertEquals(objObj, TypeData.commonSuperClassEx(strObj, str));
  124. assertEquals(obj, TypeData.commonSuperClassEx(array, array2));
  125. assertEquals(obj, TypeData.commonSuperClassEx(base, array2));
  126. }
  127. public void testRebuild() throws Exception {
  128. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T1");
  129. rebuildStackMaps2(cc);
  130. //Class c = cc.toClass();
  131. //Object t1 = c.getConstructor().newInstance();
  132. cc.writeFile();
  133. Object t1 = make(cc.getName());
  134. assertEquals(3, invoke(t1, "test"));
  135. }
  136. public static interface Intf {
  137. int foo();
  138. }
  139. public static class C1 implements Intf {
  140. public int foo() { return 0; }
  141. }
  142. public static class C2 implements Intf {
  143. public int foo() { return 3; }
  144. }
  145. public static class T1 {
  146. public int test() {
  147. return foo(-1);
  148. }
  149. public int foo(int i) {
  150. Intf obj;
  151. if (i > 0)
  152. obj = new C1();
  153. else
  154. obj = new C2();
  155. return obj.foo();
  156. }
  157. }
  158. public void testRebuild2() throws Exception {
  159. CtClass cc = loader.get("javassist.bytecode.StackMapTest$C3");
  160. rebuildStackMaps2(cc);
  161. cc.writeFile();
  162. Object t1 = make(cc.getName());
  163. assertEquals(7, invoke(t1, "test"));
  164. }
  165. public static class C3 {
  166. int value;
  167. public C3(int i) {
  168. value = i;
  169. }
  170. public C3(boolean b) {
  171. this(b ? 7 : 10);
  172. }
  173. public C3() { this(true); }
  174. public int test() { return value; }
  175. }
  176. public void testRebuild3() throws Exception {
  177. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T3");
  178. rebuildStackMaps2(cc);
  179. cc.writeFile();
  180. Object t1 = make(cc.getName());
  181. assertEquals(1100, invoke(t1, "test"));
  182. }
  183. public static interface Intf2 {
  184. int bar();
  185. }
  186. public static class D1 extends C1 implements Intf2 {
  187. public int bar() { return 10; }
  188. }
  189. public static class D2 extends C1 implements Intf2 {
  190. public int bar() { return 100; }
  191. }
  192. public static class T3 {
  193. public int bar(Intf2 i) { return 1000; }
  194. public int test() {
  195. return foo(-1);
  196. }
  197. public int foo(int i) {
  198. Intf2 obj;
  199. if (i > 0)
  200. obj = new D1();
  201. else
  202. obj = new D2();
  203. System.out.println(obj.toString());
  204. return obj.bar() + bar(obj);
  205. }
  206. }
  207. public void testRebuildArray() throws Exception {
  208. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T4");
  209. rebuildStackMaps2(cc);
  210. cc.writeFile();
  211. Object t1 = make(cc.getName());
  212. assertEquals(30, invoke(t1, "test"));
  213. }
  214. public static class T4 {
  215. public int test() {
  216. return foo(3) + foo2(3) + foo3(3) + foo4(3);
  217. }
  218. public int foo(int i) {
  219. C1[] a;
  220. if (i > 0)
  221. a = new D1[1];
  222. else
  223. a = new D2[1];
  224. if (i > 0)
  225. a[0] = new D1();
  226. else
  227. a[0] = new D2();
  228. return a[0].foo();
  229. }
  230. public int foo2(int i) {
  231. Intf2[] a;
  232. if (i > 0)
  233. a = new D1[1];
  234. else
  235. a = new D2[1];
  236. if (i > 0)
  237. a[0] = new D1();
  238. else
  239. a[0] = new D2();
  240. return a[0].bar();
  241. }
  242. public int foo3(int i) {
  243. Intf2[] a = null;
  244. if (i > 0)
  245. a = new D1[1];
  246. a[0] = new D1();
  247. return a[0].bar();
  248. }
  249. public int foo4(int i) {
  250. Intf2[] a = new Intf2[1];
  251. if (i > 0)
  252. a[0] = new D1();
  253. return a[0].bar();
  254. }
  255. }
  256. public void testRebuildConstructor() throws Exception {
  257. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T5");
  258. rebuildStackMaps2(cc);
  259. cc.writeFile();
  260. Object t1 = make(cc.getName());
  261. assertEquals(123, invoke(t1, "test"));
  262. }
  263. public static class T5 {
  264. int count;
  265. public T5() { count = 0; }
  266. public T5(int k) {
  267. if (k > 0) count = 10;
  268. else count = 100;
  269. count++;
  270. }
  271. public T5(double d) {
  272. this(d > 0.0 ? 1 : -1);
  273. if (d > 1.0) count += 10;
  274. else count += 100;
  275. count++;
  276. }
  277. public int test() {
  278. return new T5(3).count + new T5(1.0).count;
  279. }
  280. }
  281. public void testRebuildConstructor2() throws Exception {
  282. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T6");
  283. rebuildStackMaps2(cc);
  284. cc.writeFile();
  285. Object t1 = make(cc.getName());
  286. assertEquals(101, invoke(t1, "test2"));
  287. }
  288. public static class T6 {
  289. public int test2() {
  290. T5 t0 = new T5();
  291. T5 t = new T5(t0.count > 0 ? (new T5(t0.count > 0 ? 1 : -1).count) : -1);
  292. if (t0.count > 0)
  293. t.count += 1000;
  294. return t.count;
  295. }
  296. }
  297. public void testSwitchCase() throws Exception {
  298. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T7");
  299. // CodeConverter conv = new CodeConverter();
  300. // conv.replaceNew(cc, cc, "make2");
  301. // cc.instrument(conv);
  302. StringBuffer sbuf = new StringBuffer("String s;");
  303. for (int i = 0; i < 130; i++)
  304. sbuf.append("s =\"" + i + "\";");
  305. cc.getDeclaredMethod("foo").insertBefore(sbuf.toString());
  306. cc.getDeclaredMethod("test2").setBody(loader.get("javassist.bytecode.StackMapTest$T8").getDeclaredMethod("test2"), null);
  307. //rebuildStackMaps2(cc);
  308. cc.writeFile();
  309. Object t1 = make(cc.getName());
  310. assertEquals(110, invoke(t1, "test"));
  311. }
  312. public static class T7 {
  313. int value = 1;
  314. T7 t7;
  315. public static T7 make2() { return null; }
  316. public int foo() { return 1; }
  317. public int test() { return test2(10); }
  318. public int test2(int k) { return k; }
  319. }
  320. public static class T8 {
  321. public int test2(int k) {
  322. String s = "abc";
  323. T7 t = k > 0 ? new T7() : new T7();
  324. switch (k) {
  325. case 0:
  326. t = new T7();
  327. k += t.value;
  328. break;
  329. case 10:
  330. k += 100;
  331. break;
  332. }
  333. return k;
  334. }
  335. }
  336. public void testSwitchCase2() throws Exception {
  337. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T7b");
  338. StringBuffer sbuf = new StringBuffer("String s;");
  339. for (int i = 0; i < 130; i++)
  340. sbuf.append("s =\"" + i + "\";");
  341. cc.getDeclaredMethod("foo").insertBefore(sbuf.toString());
  342. cc.getDeclaredMethod("test2").setBody(loader.get("javassist.bytecode.StackMapTest$T8b").getDeclaredMethod("test2"), null);
  343. rebuildStackMaps2(cc);
  344. cc.writeFile();
  345. Object t1 = make(cc.getName());
  346. assertEquals(110, invoke(t1, "test"));
  347. }
  348. public static class T7b {
  349. int value = 1;
  350. T7b t7;
  351. public static T7b make2() { return null; }
  352. public int foo() { return 1; }
  353. public int test() { return test2(10); }
  354. public int test2(int k) { return k; }
  355. }
  356. public static class T8b {
  357. public int test2(int k) {
  358. String s = "abc";
  359. T7b t = k > 0 ? new T7b() : new T7b();
  360. switch (k) {
  361. case 0:
  362. t = new T7b();
  363. k += t.value;
  364. break;
  365. case 10:
  366. k += 100;
  367. break;
  368. }
  369. return k;
  370. }
  371. }
  372. public void testSwitchCase3() throws Exception {
  373. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T7c");
  374. StringBuffer sbuf = new StringBuffer("String s;");
  375. for (int i = 0; i < 130; i++)
  376. sbuf.append("s =\"" + i + "\";");
  377. cc.getDeclaredMethod("foo").insertBefore(sbuf.toString());
  378. cc.getDeclaredMethod("test2").setBody(loader.get("javassist.bytecode.StackMapTest$T8c").getDeclaredMethod("test2"), null);
  379. cc.writeFile();
  380. Object t1 = make(cc.getName());
  381. assertEquals(100, invoke(t1, "test"));
  382. }
  383. public static class T7c {
  384. int value = 1;
  385. T7b t7;
  386. public static T7b make2() { return null; }
  387. public static void print(String s) {}
  388. public int foo() { return 1; }
  389. public int test() { return test2(10); }
  390. public int test2(int k) { return 0; }
  391. }
  392. public static class T8c {
  393. public int test2(int k) {
  394. int jj = 50;
  395. if (k > 0)
  396. k += "fooo".length();
  397. int j = 50;
  398. loop: for (int i = 0; i < 10; i++) {
  399. int jjj = 1;
  400. switch (i) {
  401. case 0:
  402. k++;
  403. { int poi = 0; }
  404. break;
  405. case 9:
  406. break loop;
  407. case 7:
  408. k += jjj;
  409. break;
  410. }
  411. }
  412. return j + jj;
  413. }
  414. }
  415. public void testSwitchCase4() throws Exception {
  416. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T8e");
  417. StringBuffer sbuf = new StringBuffer("String s;");
  418. for (int i = 0; i < 130; i++)
  419. sbuf.append("s =\"" + i + "\";");
  420. cc.getDeclaredMethod("foo").insertBefore(sbuf.toString());
  421. CtClass orig = loader.get("javassist.bytecode.StackMapTest$T8d");
  422. CtMethod origM = orig.getDeclaredMethod("test2");
  423. writeLdcw(origM);
  424. cc.getDeclaredMethod("test2").setBody(origM, null);
  425. orig.writeFile();
  426. cc.writeFile();
  427. Object t1 = make(cc.getName());
  428. assertEquals(100, invoke(t1, "test"));
  429. }
  430. private void writeLdcw(CtMethod method) {
  431. CodeAttribute ca = method.getMethodInfo().getCodeAttribute();
  432. int index = ca.getConstPool().addStringInfo("ldcw");
  433. CodeIterator ci = ca.iterator();
  434. ci.writeByte(Opcode.LDC_W, 14);
  435. ci.write16bit(index, 15);
  436. ci.writeByte(Opcode.LDC_W, 43);
  437. ci.write16bit(index, 44);
  438. }
  439. public static class T8e {
  440. static T8dd helper() { return new T8dd(); }
  441. int integer() { return 9; }
  442. boolean integer2(String s) { return true; }
  443. static void print(String s) {}
  444. private void print2(String s) {}
  445. private Object func(String s) { return null; }
  446. I8d func2(String s) { return null; }
  447. static String ldcw() { return "k"; }
  448. static boolean debug = false;
  449. void log(String p1,String p2,String p3,Long p4, Object p5, Object p6) {}
  450. public int foo() { return 1; }
  451. public int test() {
  452. try {
  453. return test2("", 10) ? 1 : 0;
  454. } catch (Exception e) {}
  455. return 100;
  456. }
  457. public boolean test2(String s, int k) throws Exception { return false; }
  458. }
  459. public static interface I8d {
  460. String foo(String s, int i);
  461. }
  462. public static class T8dd {
  463. java.util.List foo(String s) { return new java.util.ArrayList(); }
  464. }
  465. public static class T8d {
  466. static T8dd helper() { return new T8dd(); }
  467. int integer() { return 9; }
  468. boolean integer2(String s) { return true; }
  469. static void print(String s) {}
  470. private void print2(String s) {}
  471. private Object func(String s) { return null; }
  472. I8d func2(String s) { return null; }
  473. static String ldcw() { return "k"; }
  474. static boolean debug = false;
  475. void log(String p1,String p2,String p3,Long p4, Object p5, Object p6) {}
  476. public boolean test2(String s, int i) throws Exception {
  477. String k = null;
  478. Object k2 = null;
  479. boolean v5 = true;
  480. if (!debug)
  481. print(ldcw());
  482. Object k3 = this.func(s);
  483. if (k3 == null)
  484. throw new Exception(new StringBuilder().append(ldcw()).append(s).append(",").toString());
  485. String v7 = k3.toString();
  486. k2 = this.func2(v7);
  487. if (k2 != null) { // 82:
  488. if (k2 instanceof I8d) {
  489. I8d k5 = (I8d)k2;
  490. k = k5.foo(s, i);
  491. }
  492. }
  493. java.util.List list = helper().foo(v7); // local 8
  494. for (int v9 = 0; v9 < list.size(); v9++) {
  495. boolean v10 = true;
  496. T8d v11 = (T8d)list.get(v9);
  497. switch (v11.integer()) {
  498. case 1:
  499. break;
  500. case 2:
  501. v10 = this.integer2(s);
  502. v5 &= v10;
  503. break;
  504. default :
  505. throw new Exception(new StringBuilder().append("ldc 189").append(v11.integer()).append("ldc 169").toString());
  506. }
  507. }
  508. if (v5) // 246:
  509. this.print2(s);
  510. if (v5)
  511. this.log(ldcw(), v7, s, Long.valueOf(Integer.valueOf(i).longValue()), k, null);
  512. else // 290:
  513. this.log(ldcw(), v7, s, Long.valueOf(Integer.valueOf(i).longValue()), k, null);
  514. return v5;
  515. }
  516. }
  517. public void testInnerClass() throws Exception {
  518. CtClass cc = loader.get("javassist.bytecode.StackMapTest$T9");
  519. CtClass par = loader.get("javassist.bytecode.StackMapTest$T9$Parent");
  520. CtClass in = loader.get("javassist.bytecode.StackMapTest$T9$In");
  521. rebuildStackMaps2(cc);
  522. rebuildStackMaps2(par);
  523. rebuildStackMaps2(in);
  524. cc.writeFile();
  525. in.writeFile();
  526. par.writeFile();
  527. Object t1 = make(cc.getName());
  528. assertEquals(19, invoke(t1, "test"));
  529. }
  530. public static class T9 {
  531. class Parent {
  532. int f;
  533. Parent(int i) { f = i; }
  534. }
  535. class In extends Parent {
  536. int value;
  537. public In(int i) {
  538. super(i > 0 ? 10 : 20);
  539. value = i;
  540. }
  541. }
  542. public int test() {
  543. In in = new In(9);
  544. return in.value + in.f;
  545. }
  546. }
  547. public void testConstructor3() throws Exception {
  548. CtClass cc = loader.get("javassist.bytecode.StackMapTest$C4");
  549. MethodInfo mi = cc.getDeclaredMethod("foo").getMethodInfo();
  550. mi.rebuildStackMapForME(loader);
  551. CodeIterator ci = mi.getCodeAttribute().iterator();
  552. ci.insertGap(0, 7);
  553. cc.writeFile();
  554. Object t1 = make(cc.getName());
  555. assertEquals(6, invoke(t1, "test"));
  556. }
  557. public static class C4 {
  558. public int test() { return foo(3); }
  559. public int foo(int i) {
  560. String s = new String(i > 0 ? "pos" : "negative");
  561. System.out.println("2nd stage");
  562. int len = 0;
  563. if (i > 0) {
  564. String t = new String(i > 0 ? "pos" : "negative");
  565. len = t.length();
  566. }
  567. return s.length() + len;
  568. }
  569. }
  570. public void testJIRA175() throws Exception {
  571. CtClass cc = loader.get("javassist.bytecode.StackMapTest$C5");
  572. cc.getDeclaredMethod("setter").instrument(new javassist.expr.ExprEditor() {
  573. @Override
  574. public void edit(javassist.expr.FieldAccess f) throws javassist.CannotCompileException {
  575. if (!f.where().getMethodInfo().isMethod())
  576. return;
  577. f.replace("{ $_ = $proceed($$); if (false) return $_;}");
  578. }
  579. });
  580. cc.writeFile();
  581. Object t1 = make(cc.getName());
  582. assertEquals(3, invoke(t1, "test"));
  583. }
  584. public static class C5 {
  585. String value;
  586. int ivalue;
  587. public int test() {
  588. setter("foo");
  589. return value.length();
  590. }
  591. public void setter(String s) {
  592. value = s;
  593. ivalue = s.length();
  594. }
  595. }
  596. public void testJIRA175b() throws Exception {
  597. CtClass cc = loader.get("javassist.bytecode.StackMapTest$C6");
  598. cc.getDeclaredMethod("setter").instrument(new javassist.expr.ExprEditor() {
  599. public void edit(javassist.expr.FieldAccess f) throws javassist.CannotCompileException {
  600. if (!f.where().getMethodInfo().isMethod())
  601. return;
  602. // this will make a 1-byte dead code.
  603. f.replace("{ $_ = $proceed($$); return $_;}");
  604. }
  605. });
  606. cc.writeFile();
  607. }
  608. public static class C6 {
  609. String value;
  610. int ivalue;
  611. public int test() {
  612. setter("foo");
  613. return value.length();
  614. }
  615. public void setter(String s) {
  616. value = s;
  617. ivalue = s.length();
  618. }
  619. }
  620. public void testForHibernate() throws Exception {
  621. ClassFile cf = loader.makeClass("javassist.bytecode.StackMapTestHibTest").getClassFile();
  622. ConstPool cp = cf.getConstPool();
  623. MethodInfo mi = new MethodInfo(cp, "foo", "()V");
  624. Bytecode code = new Bytecode(cp, 0, 0);
  625. code.add(Opcode.RETURN);
  626. CodeAttribute ca = code.toCodeAttribute();
  627. mi.addAttribute(ca);
  628. cf.addMethod(mi);
  629. int pc = 111;
  630. int throwableType_index = cp.addClassInfo(Throwable.class.getName());
  631. StackMapTable.Writer writer = new StackMapTable.Writer(32);
  632. int[] localTags = { StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.INTEGER };
  633. int[] localData = { cp.getThisClassInfo(), cp.addClassInfo("java/lang/Object"),
  634. cp.addClassInfo("[Ljava/lang/Object;"), 0};
  635. int[] stackTags = { StackMapTable.OBJECT };
  636. int[] stackData = { throwableType_index };
  637. writer.fullFrame(pc, localTags, localData, stackTags, stackData);
  638. ca.setAttribute(writer.toStackMapTable(cp));
  639. cf.write(new java.io.DataOutputStream(new java.io.FileOutputStream("./test-hibernate.class")));
  640. }
  641. public void testCommonSuperclass() throws Exception {
  642. CtClass obj = loader.get("java.lang.Object");
  643. CtClass objarray = loader.get("java.lang.Object[]");
  644. CtClass one = loader.get("byte[]");
  645. CtClass two = loader.get("byte[][]");
  646. assertEquals("java.lang.Object", TypeData.commonSuperClassEx(one, two).getName());
  647. assertTrue(one.subtypeOf(obj));
  648. assertTrue(two.subtypeOf(obj));
  649. assertFalse(one.subtypeOf(objarray));
  650. assertTrue(two.subtypeOf(objarray));
  651. one = loader.get("int[][]");
  652. two = loader.get("java.lang.Object[]");
  653. assertEquals("java.lang.Object[]", TypeData.commonSuperClassEx(one, two).getName());
  654. assertTrue(one.subtypeOf(objarray));
  655. assertTrue(two.subtypeOf(objarray));
  656. one = loader.get("int[]");
  657. two = loader.get("java.lang.String");
  658. assertEquals("java.lang.Object", TypeData.commonSuperClassEx(one, two).getName());
  659. assertTrue(one.subtypeOf(obj));
  660. assertTrue(two.subtypeOf(obj));
  661. assertFalse(one.subtypeOf(objarray));
  662. assertFalse(two.subtypeOf(objarray));
  663. one = loader.get("int[]");
  664. two = loader.get("int[]");
  665. assertEquals("int[]", TypeData.commonSuperClassEx(one, two).getName());
  666. assertTrue(one.subtypeOf(obj));
  667. assertFalse(one.subtypeOf(objarray));
  668. one = loader.get("int[]");
  669. two = loader.get("java.lang.String[]");
  670. assertEquals("java.lang.Object", TypeData.commonSuperClassEx(one, two).getName());
  671. assertTrue(one.subtypeOf(obj));
  672. assertTrue(two.subtypeOf(obj));
  673. assertFalse(one.subtypeOf(objarray));
  674. assertTrue(two.subtypeOf(objarray));
  675. one = loader.get("java.lang.String[]");
  676. two = loader.get("java.lang.Class[]");
  677. assertEquals("java.lang.Object[]", TypeData.commonSuperClassEx(one, two).getName());
  678. assertTrue(one.subtypeOf(objarray));
  679. assertTrue(two.subtypeOf(objarray));
  680. }
  681. public void testJsr() throws Exception {
  682. CtClass cc = loader.makeClass("javassist.bytecode.StackMapTestJsrTest");
  683. ClassFile cf = cc.getClassFile();
  684. cf.setMajorVersion(ClassFile.JAVA_5);
  685. ConstPool cp = cf.getConstPool();
  686. MethodInfo mi = new MethodInfo(cp, "test", "()I");
  687. mi.setAccessFlags(AccessFlag.PUBLIC);
  688. Bytecode code = new Bytecode(cp, 1, 3);
  689. code.addIconst(3);
  690. code.addIstore(1);
  691. code.addIload(1);
  692. code.add(Opcode.IFEQ);
  693. code.addIndex(6);
  694. code.add(Opcode.JSR);
  695. code.addIndex(5);
  696. code.addIload(1);
  697. code.add(Opcode.IRETURN);
  698. code.addAstore(2);
  699. code.addRet(2);
  700. CodeAttribute ca = code.toCodeAttribute();
  701. mi.addAttribute(ca);
  702. mi.rebuildStackMap(loader);
  703. cf.addMethod(mi);
  704. cc.addConstructor(CtNewConstructor.make("public StackMapTestJsrTest() {}", cc));
  705. cc.addMethod(CtMethod.make("public static void main(String[] args) {"
  706. + "new javassist.bytecode.StackMapTestJsrTest().test();"
  707. + "}",
  708. cc));
  709. cc.writeFile();
  710. Object t1 = make(cc.getName());
  711. assertEquals(3, invoke(t1, "test"));
  712. }
  713. public void tstCtClassType() throws Exception {
  714. ClassPool cp = ClassPool.getDefault();
  715. CtClass cc = cp.get("javassist.CtClassType");
  716. MethodInfo minfo = getMethodInfo(cc.getClassFile(), "getFields", "(Ljava/util/ArrayList;Ljavassist/CtClass;)V");
  717. rebuildStackMap(cc, cp, minfo);
  718. }
  719. MethodInfo getMethodInfo(ClassFile cf, String name, String desc) {
  720. List list = cf.getMethods();
  721. Iterator it = list.iterator();
  722. while (it.hasNext()) {
  723. MethodInfo mi = (MethodInfo)it.next();
  724. if (mi.getName().equals(name) && mi.getDescriptor().equals(desc))
  725. return mi;
  726. }
  727. return null;
  728. }
  729. public static class C7 {
  730. public int value;
  731. public static int value2;
  732. public C7() { this(3); }
  733. public C7(int i) {
  734. value = i;
  735. }
  736. }
  737. public void testIssue328() throws Exception {
  738. CtClass cc = loader.get("javassist.bytecode.StackMapTest$C7");
  739. CtConstructor cons = cc.getDeclaredConstructor(new CtClass[] { CtClass.intType });
  740. cons.insertBefore("if ($1 < 0) { super(); if (value2 > 0) { value2++; } return; }");
  741. cc.writeFile();
  742. Object t1 = make(cc.getName());
  743. }
  744. public static class C8 {
  745. int value = 0;
  746. int loop = 0;
  747. int loop2 = 1;
  748. public void foo(int i) { value += i; }
  749. public void bar(int i) { value += i; }
  750. public void foo2(int i) { value += i; }
  751. public void bar2(int i) { value += i; }
  752. }
  753. public static class C9 extends C8 {
  754. public void foo(int i) {
  755. while(true) {
  756. loop--;
  757. if (loop < 0)
  758. break;
  759. }
  760. value += i;
  761. }
  762. public void bar(int i) {
  763. value += i;
  764. for (int k = 0; i < 10; k++)
  765. loop += k;
  766. }
  767. public void foo2(int i) {
  768. while(true) {
  769. loop2--;
  770. if (loop2 < 0)
  771. break;
  772. }
  773. value += i;
  774. for (int k = 0; k < 3; k++)
  775. loop2--;
  776. }
  777. public void bar2(int i) {
  778. value += i;
  779. for (int k = 0; i < 10; k++)
  780. loop += k;
  781. }
  782. public int run() {
  783. foo(1);
  784. bar(10);
  785. foo2(100);
  786. bar2(1000);
  787. return value;
  788. }
  789. }
  790. public void testIssue339() throws Exception {
  791. CtClass cc0 = loader.get("javassist.bytecode.StackMapTest$C8");
  792. CtClass cc = loader.get("javassist.bytecode.StackMapTest$C9");
  793. testIssue339b(cc, cc0, "foo", true);
  794. testIssue339b(cc, cc0, "bar", true);
  795. testIssue339b(cc, cc0, "foo2", false);
  796. testIssue339b(cc, cc0, "bar2", false);
  797. cc.writeFile();
  798. Object t1 = make(cc.getName());
  799. assertEquals(2322, invoke(t1, "run"));
  800. }
  801. public void testIssue339b(CtClass cc, CtClass cc0, String name, boolean exclusive) throws Exception {
  802. Bytecode newCode = new Bytecode(cc.getClassFile().constPool);
  803. newCode.addAload(0); // Loads 'this'
  804. newCode.addIload(1); // Loads method param 1 (int)
  805. newCode.addInvokespecial(cc0.getName(), name, "(I)V");
  806. CodeAttribute ca = cc.getDeclaredMethod(name).getMethodInfo().getCodeAttribute();
  807. CodeIterator ci = ca.iterator();
  808. if (exclusive)
  809. ci.insertEx(newCode.get());
  810. else
  811. ci.insert(newCode.get());
  812. }
  813. }