Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

StackMapTest.java 27KB

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