Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

BytecodeTest.java 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. package javassist.bytecode;
  2. import java.io.*;
  3. import java.lang.reflect.Method;
  4. import junit.framework.*;
  5. import javassist.*;
  6. import javassist.bytecode.annotation.*;
  7. import javassist.bytecode.SignatureAttribute.*;
  8. @SuppressWarnings("unused")
  9. public class BytecodeTest extends TestCase {
  10. public static final String PATH = JvstTest.PATH;
  11. private ClassPool loader, dloader;
  12. private Loader cloader;
  13. public BytecodeTest(String name) {
  14. super(name);
  15. }
  16. protected void print(String msg) {
  17. System.out.println(msg);
  18. }
  19. protected void setUp() throws Exception {
  20. loader = ClassPool.getDefault();
  21. dloader = new ClassPool(null);
  22. dloader.appendSystemPath();
  23. dloader.insertClassPath(".");
  24. cloader = new Loader(dloader);
  25. }
  26. protected Object make(String name) throws Exception {
  27. return cloader.loadClass(name).getConstructor().newInstance();
  28. }
  29. protected int invoke(Object target, String method) throws Exception {
  30. Method m = target.getClass().getMethod(method, new Class[0]);
  31. Object res = m.invoke(target, new Object[0]);
  32. return ((Integer)res).intValue();
  33. }
  34. public void testByteVector() throws Exception {
  35. final int N = 257;
  36. Bytecode code = new Bytecode(null);
  37. for (int i = 0; i < N; i++) {
  38. code.add(i);
  39. assertEquals(i + 1, code.length());
  40. assertEquals((int)(byte)i, code.read(i));
  41. code.write(i, i + 1);
  42. assertEquals((int)(byte)(i + 1), code.read(i));
  43. }
  44. byte[] b = code.copy();
  45. assertEquals(N, b.length);
  46. for (int i = 0; i < N; i++)
  47. assertEquals((int)(byte)(i + 1), b[i]);
  48. code = new Bytecode(null);
  49. code.add(1);
  50. code.addGap(100);
  51. code.add(2);
  52. assertEquals(2, code.read(101));
  53. }
  54. public void testLongVector() throws Exception {
  55. LongVector vec = new LongVector();
  56. assertEquals(LongVector.ASIZE * LongVector.VSIZE, vec.capacity());
  57. int size = LongVector.ASIZE * LongVector.VSIZE * 3;
  58. for (int i = 0; i < size; i++) {
  59. vec.addElement(new IntegerInfo(i, i));
  60. assertEquals(i, ((IntegerInfo)vec.elementAt(i)).value);
  61. assertEquals(i + 1, vec.size());
  62. }
  63. size = LongVector.ASIZE * LongVector.VSIZE * 3;
  64. vec = new LongVector(size - 5);
  65. assertEquals(size, vec.capacity());
  66. for (int i = 0; i < size; i++) {
  67. vec.addElement(new IntegerInfo(i, i));
  68. assertEquals(i, ((IntegerInfo)vec.elementAt(i)).value);
  69. assertEquals(i + 1, vec.size());
  70. }
  71. }
  72. public void testClone() throws Exception {
  73. ConstPool cp = new ConstPool("test.CloneTest");
  74. Bytecode bc = new Bytecode(cp);
  75. bc.add(7);
  76. bc.add(11);
  77. Bytecode bc2 = (Bytecode)bc.clone();
  78. bc2.add(13);
  79. bc2.write(0, 17);
  80. assertEquals(7, bc.read(0));
  81. assertEquals(2, bc.length());
  82. assertEquals(3, bc2.length());
  83. assertEquals(cp, bc2.getConstPool());
  84. assertTrue(bc.getExceptionTable() != bc2.getExceptionTable());
  85. }
  86. public void test2byteLocalVar() throws Exception {
  87. CtClass cc = loader.makeClass("test.LocalVar2");
  88. CtMethod m = CtNewMethod.abstractMethod(CtClass.intType, "test",
  89. null, null, cc);
  90. Bytecode code = new Bytecode(cc.getClassFile().getConstPool(), 2, 300);
  91. code.addIconst(1);
  92. code.addIstore(255);
  93. code.addIload(255);
  94. code.addIstore(256);
  95. code.addIload(256);
  96. code.addLconst(1);
  97. code.addLstore(255);
  98. code.addLload(255);
  99. code.addLstore(256);
  100. code.addLload(256);
  101. code.addFconst(1.0f);
  102. code.addFstore(255);
  103. code.addFload(255);
  104. code.addFstore(256);
  105. code.addFload(256);
  106. code.addDconst(1.0);
  107. code.addDstore(255);
  108. code.addDload(255);
  109. code.addDstore(256);
  110. code.addDload(256);
  111. code.addOpcode(Opcode.ACONST_NULL);
  112. code.addAstore(255);
  113. code.addAload(255);
  114. code.addAstore(256);
  115. code.addAload(256);
  116. code.addIconst(1);
  117. code.addOpcode(Opcode.IRETURN);
  118. m.getMethodInfo().setCodeAttribute(code.toCodeAttribute());
  119. m.setModifiers(Modifier.PUBLIC);
  120. cc.addMethod(m);
  121. cc.writeFile();
  122. Object obj = make(cc.getName());
  123. assertEquals(1, invoke(obj, "test"));
  124. }
  125. public void testBytecode() throws Exception {
  126. final int N = 64;
  127. Bytecode b = new Bytecode(null, 0, 0);
  128. try {
  129. b.write(3, 3);
  130. throw new Exception("out of range");
  131. }
  132. catch (ArrayIndexOutOfBoundsException e) {}
  133. try {
  134. b.read(3);
  135. throw new Exception("out of range");
  136. }
  137. catch (ArrayIndexOutOfBoundsException e) {}
  138. for (int i = 0; i < N * 3; ++i) {
  139. b.add(i % 100);
  140. assertEquals(i % 100, b.read(i));
  141. }
  142. for (int i = 0; i < N * 3; ++i)
  143. assertEquals(i % 100, b.read(i));
  144. for (int i = 0; i < N * 3; ++i) {
  145. b.write(i, i % 100);
  146. assertEquals(i % 100, b.read(i));
  147. }
  148. for (int i = 0; i < N * 3; ++i)
  149. assertEquals(i % 100, b.read(i));
  150. }
  151. public void testBytecode2() throws Exception {
  152. final int N = 64;
  153. Bytecode b = new Bytecode(null, 0, 0);
  154. for (int i = 0; i < N * 3 / 16; ++i) {
  155. b.addGap(16);
  156. assertEquals(16 * (i + 1), b.length());
  157. }
  158. b = new Bytecode(null, 0, 0);
  159. for (int i = 0; i < N * 3 / 10; ++i) {
  160. b.addGap(10);
  161. assertEquals(10 * (i + 1), b.length());
  162. }
  163. }
  164. public void testDescriptor() throws Exception {
  165. assertEquals("(II)", Descriptor.getParamDescriptor("(II)V"));
  166. assertEquals("()", Descriptor.getParamDescriptor("()I"));
  167. assertEquals(1, Descriptor.dataSize("I"));
  168. assertEquals(2, Descriptor.dataSize("D"));
  169. assertEquals(2, Descriptor.dataSize("J"));
  170. assertEquals(1, Descriptor.dataSize("[J"));
  171. assertEquals(1, Descriptor.dataSize("[[D"));
  172. assertEquals(1, Descriptor.dataSize("LD;"));
  173. assertEquals(-1, Descriptor.dataSize("(I)V"));
  174. assertEquals(0, Descriptor.dataSize("(D)J"));
  175. assertEquals(0, Descriptor.dataSize("()V"));
  176. assertEquals(1, Descriptor.dataSize("()I"));
  177. assertEquals(-1, Descriptor.dataSize("([DLA;)I"));
  178. assertEquals(-3, Descriptor.dataSize("(BIJ)LA;"));
  179. assertEquals(-3, Descriptor.dataSize("(BIJ)[D"));
  180. boolean ok = false;
  181. try {
  182. Descriptor.dataSize("(Ljava/lang/String)I");
  183. }
  184. catch (IndexOutOfBoundsException e) {
  185. print("testDescriptor(): dataSize() " + e);
  186. ok = true;
  187. }
  188. assertTrue(ok);
  189. ok = false;
  190. try {
  191. Descriptor.numOfParameters("([DLjava/lang/String)I");
  192. }
  193. catch (IndexOutOfBoundsException e) {
  194. print("testDescriptor(): numOfParameters() " + e);
  195. ok = true;
  196. }
  197. assertTrue(ok);
  198. }
  199. public void testDescriptor2() throws Exception {
  200. assertEquals("int", Descriptor.toClassName("I"));
  201. assertEquals("double[]", Descriptor.toClassName("[D"));
  202. assertEquals("boolean[][]", Descriptor.toClassName("[[Z"));
  203. assertEquals("java.lang.String",
  204. Descriptor.toClassName("Ljava/lang/String;"));
  205. assertEquals("java.lang.String[]",
  206. Descriptor.toClassName("[Ljava/lang/String;"));
  207. try {
  208. assertEquals("Foo", Descriptor.toClassName("LFoo;;"));
  209. fail("LFoo;;");
  210. }
  211. catch (RuntimeException e) {}
  212. try {
  213. assertEquals("int", Descriptor.toClassName("II"));
  214. fail("II");
  215. }
  216. catch (RuntimeException e) {}
  217. }
  218. public void testLineNumberAttribute() throws Exception {
  219. CtClass cc = loader.get("test1.LineNumber");
  220. CtMethod m = cc.getDeclaredMethod("sort");
  221. MethodInfo minfo = m.getMethodInfo();
  222. CodeAttribute ca = minfo.getCodeAttribute();
  223. LineNumberAttribute ainfo
  224. = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
  225. int n = ainfo.tableLength();
  226. for (int i = 0; i < n; ++i)
  227. print("Line " + ainfo.lineNumber(i) + " at " + ainfo.startPc(i));
  228. print("find Line 10: " + ainfo.toStartPc(10));
  229. print("find PC 30: " + ainfo.toLineNumber(30));
  230. LineNumberAttribute.Pc pc = ainfo.toNearPc(6);
  231. print("line 6: " + pc.index);
  232. assertEquals(8, pc.line);
  233. pc = ainfo.toNearPc(7);
  234. print("line 7: " + pc.index);
  235. assertEquals(8, pc.line);
  236. pc = ainfo.toNearPc(8);
  237. print("line 8: " + pc.index);
  238. assertEquals(8, pc.line);
  239. pc = ainfo.toNearPc(9);
  240. print("line 9: " + pc.index);
  241. assertEquals(9, pc.line);
  242. pc = ainfo.toNearPc(15);
  243. print("line 15: " + pc.index);
  244. assertEquals(17, pc.line);
  245. pc = ainfo.toNearPc(19);
  246. print("line 19: " + pc.index);
  247. assertEquals(20, pc.line);
  248. pc = ainfo.toNearPc(21);
  249. print("line 20: " + pc.index);
  250. assertEquals(20, pc.line);
  251. pc = ainfo.toNearPc(22);
  252. print("line 21: " + pc.index);
  253. assertEquals(20, pc.line);
  254. }
  255. public void testLineNumberCompiler() {
  256. CtClass testClass = loader.makeClass("javassist.bytecode.LineNumberCompilerClass");
  257. String run = String.join("\n",
  258. "public void run() {",
  259. " return",
  260. "}");
  261. try {
  262. testClass.addMethod(CtMethod.make(run, testClass));
  263. } catch (CannotCompileException e) {
  264. assertEquals("line 3: syntax error near \" return\n}\"", e.getCause().getMessage());
  265. return;
  266. }
  267. fail("should not happen");
  268. }
  269. public void testLineNumberCompiler2() {
  270. CtClass testClass = loader.makeClass("javassist.bytecode.LineNumberCompilerClass2");
  271. String ctor = String.join("\n",
  272. "public LineNumberCompilerClass2() {",
  273. " super();",
  274. "}");
  275. String run = String.join("\n",
  276. "public void run() {",
  277. " return;",
  278. "}");
  279. String run2 = String.join("\n",
  280. "public void run2() {",
  281. " run()",
  282. "}");
  283. try {
  284. testClass.addConstructor(CtNewConstructor.make(ctor, testClass));
  285. testClass.addMethod(CtMethod.make(run, testClass));
  286. testClass.addMethod(CtMethod.make(run2, testClass));
  287. } catch (CannotCompileException e) {
  288. assertEquals("line 9: ; is missing", e.getCause().getMessage());
  289. return;
  290. }
  291. fail("should not happen");
  292. }
  293. public void testLineNumberException() {
  294. CtClass testClass = loader.makeClass("javassist.bytecode.LineNumberExceptionClass");
  295. String run = String.join("\n",
  296. "public void run() {",
  297. " throw new java.lang.RuntimeException();",
  298. "}");
  299. try {
  300. testClass.addInterface(loader.get("java.lang.Runnable"));
  301. testClass.addMethod(CtMethod.make(run, testClass));
  302. Class cls = testClass.toClass(BytecodeTest.class);
  303. var runnable = (Runnable) cls.getConstructor().newInstance();
  304. runnable.run();
  305. } catch (Exception e) {
  306. var lineNum = e.getStackTrace()[0].getLineNumber();
  307. assertEquals("Line number should be right", 2, lineNum);
  308. return;
  309. }
  310. fail("should not happen");
  311. }
  312. public void testRenameClass() throws Exception {
  313. CtClass cc = loader.get("test1.RenameClass");
  314. cc.replaceClassName("test1.RenameClass2", "java.lang.String");
  315. cc.writeFile();
  316. Object obj = make(cc.getName());
  317. assertEquals(0, invoke(obj, "test"));
  318. }
  319. public void testDeprecatedAttribute() throws Exception {
  320. CtClass cc = loader.get("java.lang.Thread");
  321. CtMethod m = cc.getDeclaredMethod("suspend");
  322. MethodInfo minfo = m.getMethodInfo();
  323. DeprecatedAttribute ainfo
  324. = (DeprecatedAttribute)minfo.getAttribute(DeprecatedAttribute.tag);
  325. assertTrue(ainfo != null);
  326. m = cc.getDeclaredMethod("toString");
  327. minfo = m.getMethodInfo();
  328. ainfo
  329. = (DeprecatedAttribute)minfo.getAttribute(DeprecatedAttribute.tag);
  330. assertTrue(ainfo == null);
  331. }
  332. public void testLocalVarAttribute() throws Exception {
  333. CtClass cc = loader.get("test1.LocalVars");
  334. CtMethod m = cc.getDeclaredMethod("foo");
  335. MethodInfo minfo = m.getMethodInfo();
  336. CodeAttribute ca = minfo.getCodeAttribute();
  337. LocalVariableAttribute ainfo
  338. = (LocalVariableAttribute)ca.getAttribute(
  339. LocalVariableAttribute.tag);
  340. assertTrue(ainfo != null);
  341. CtClass cc2 = loader.makeClass("test1.LocalVars2");
  342. CtMethod m2 = new CtMethod(m, cc2, null);
  343. CodeAttribute ca2 = m2.getMethodInfo().getCodeAttribute();
  344. ConstPool cp2 = ca2.getConstPool();
  345. LocalVariableAttribute ainfo2
  346. = (LocalVariableAttribute)ainfo.copy(cp2, null);
  347. ca2.getAttributes().add(ainfo2);
  348. cc2.addMethod(m2);
  349. cc2.writeFile();
  350. print("**** local variable table ***");
  351. for (int i = 0; i < ainfo2.tableLength(); i++) {
  352. String msg = ainfo2.startPc(i) + " " + ainfo2.codeLength(i)
  353. + " " + ainfo2.variableName(i) + " "
  354. + ainfo2.descriptor(i)
  355. + " " + ainfo2.index(i);
  356. print(msg);
  357. if (ainfo2.variableName(i).equals("j"))
  358. assertEquals("I", ainfo2.descriptor(i));
  359. }
  360. print("**** end ***");
  361. assertEquals("this", ainfo2.variableNameByIndex(0));
  362. assertEquals("i", ainfo2.variableNameByIndex(1));
  363. }
  364. public void testAnnotations() throws Exception {
  365. String fname = PATH + "annotation/Test.class";
  366. BufferedInputStream fin
  367. = new BufferedInputStream(new FileInputStream(fname));
  368. ClassFile cf = new ClassFile(new DataInputStream(fin));
  369. AnnotationsAttribute attr = (AnnotationsAttribute)
  370. cf.getAttribute(AnnotationsAttribute.invisibleTag);
  371. String sig = attr.toString();
  372. System.out.println(sig);
  373. ClassFile cf2 = new ClassFile(false, "test1.AnnoTest",
  374. "java.lang.Object");
  375. cf2.addAttribute(attr.copy(cf2.getConstPool(), null));
  376. AnnotationsAttribute attr2 = (AnnotationsAttribute)
  377. cf2.getAttribute(AnnotationsAttribute.invisibleTag);
  378. DataOutputStream out
  379. = new DataOutputStream(new FileOutputStream("test1/AnnoTest.class"));
  380. cf2.write(out);
  381. assertEquals(sig, attr2.toString());
  382. }
  383. public void testAnnotations2() throws Exception {
  384. ClassFile cf = new ClassFile(false, "test1.AnnoTest2",
  385. "java.lang.Object");
  386. AnnotationsAttribute anno
  387. = new AnnotationsAttribute(cf.getConstPool(),
  388. AnnotationsAttribute.invisibleTag);
  389. ConstPool cp = cf.getConstPool();
  390. Annotation a = new Annotation("Anno", cp);
  391. StringMemberValue smv = new StringMemberValue("foo", cp);
  392. a.addMemberValue("name", smv);
  393. anno.setAnnotation(a);
  394. cf.addAttribute(anno);
  395. String fname = "test1/AnnoTest2.class";
  396. DataOutputStream out
  397. = new DataOutputStream(new FileOutputStream(fname));
  398. cf.write(out);
  399. BufferedInputStream fin
  400. = new BufferedInputStream(new FileInputStream(fname));
  401. cf = new ClassFile(new DataInputStream(fin));
  402. AnnotationsAttribute attr = (AnnotationsAttribute)
  403. cf.getAttribute(AnnotationsAttribute.invisibleTag);
  404. String sig = attr.toString();
  405. System.out.println(sig);
  406. assertEquals("@Anno(name=\"foo\")", sig);
  407. }
  408. public void testAddClassInfo() throws Exception {
  409. CtClass cc = loader.get("test1.AddClassInfo");
  410. ClassFile cf = cc.getClassFile();
  411. ConstPool cp = cf.getConstPool();
  412. int i = cp.addClassInfo("test1.AddClassInfo");
  413. assertEquals(i, cp.getThisClassInfo());
  414. cc.addMethod(CtNewMethod.make("public int bar() { return foo(); }", cc));
  415. cc.writeFile();
  416. Object obj = make(cc.getName());
  417. assertEquals(1, invoke(obj, "bar"));
  418. }
  419. public void testRename() throws Exception {
  420. ConstPool cp = new ConstPool("test1.Foo");
  421. int i = cp.addClassInfo("test1.Bar");
  422. assertEquals(i, cp.addClassInfo("test1.Bar"));
  423. cp.renameClass("test1/Bar", "test1/Bar2");
  424. assertEquals("test1.Bar2", cp.getClassInfo(i));
  425. assertEquals(i, cp.addClassInfo("test1.Bar2"));
  426. int j = cp.addClassInfo("test1.Bar");
  427. assertTrue(i != j);
  428. assertEquals(j, cp.addClassInfo("test1.Bar"));
  429. }
  430. public void testSignature() throws Exception {
  431. parseMsig("(TT;)TT;", "<> (T) T");
  432. parseMsig("<S:Ljava/lang/Object;>(TS;[TS;)TT;",
  433. "<S extends java.lang.Object> (S, S[]) T");
  434. parseMsig("()TT;^TT;", "<> () T throws T");
  435. String sig = "<T:Ljava/lang/Exception;>LPoi$Foo<Ljava/lang/String;>;LBar;LBar2;";
  436. String rep = "<T extends java.lang.Exception> extends Poi.Foo<java.lang.String> implements Bar, Bar2";
  437. SignatureAttribute.ClassSignature cs = SignatureAttribute.toClassSignature(sig);
  438. assertEquals(rep, cs.toString());
  439. CtClass c = loader.get("test3.SigAttribute");
  440. CtField f = c.getDeclaredField("value");
  441. SignatureAttribute a = (SignatureAttribute)f.getFieldInfo2().getAttribute(SignatureAttribute.tag);
  442. assertNotNull(a);
  443. f.getFieldInfo().prune(new ConstPool("test3.SigAttribute"));
  444. a = (SignatureAttribute)f.getFieldInfo2().getAttribute(SignatureAttribute.tag);
  445. assertNotNull(a);
  446. }
  447. private void parseMsig(String sig, String rep) throws Exception {
  448. SignatureAttribute.MethodSignature ms = SignatureAttribute.toMethodSignature(sig);
  449. assertEquals(rep, ms.toString());
  450. }
  451. public void testSignatureChange() throws Exception {
  452. changeMsig("<S:Ljava/lang/Object;>(TS;[TS;)Ljava/lang/Object", "java/lang/Object",
  453. "<S:Ljava/lang/Objec;>(TS;[TS;)Ljava/lang/Object", "java/lang/Objec");
  454. changeMsig("<S:Ljava/lang/Object;>(TS;[TS;)TT;", "java/lang/Object",
  455. "<S:Ljava/lang/Objec;>(TS;[TS;)TT;", "java/lang/Objec");
  456. changeMsig("<S:Ljava/lang/Object;>(TS;[TS;)Ljava/lang/Object2;", "java/lang/Object",
  457. "<S:Ljava/lang/Objec;>(TS;[TS;)Ljava/lang/Object2;", "java/lang/Objec");
  458. changeMsig("<S:Ljava/lang/Object;>(TS;[TS;)Ljava/lang/Objec;", "java/lang/Object",
  459. "<S:Ljava/lang/Object2;>(TS;[TS;)Ljava/lang/Objec;", "java/lang/Object2");
  460. changeMsig2("<S:Ljava/lang/Object;>(TS;[TS;)TT;", "java/lang/Object",
  461. "<S:Ljava/lang/Objec;>(TS;[TS;)TT;", "java/lang/Objec");
  462. changeMsig2("<S:Ljava/lang/Object;>(TS;[TS;)Ljava/lang/Object2;", "java/lang/Object",
  463. "<S:Ljava/lang/Objec;>(TS;[TS;)Ljava/lang/Object2;", "java/lang/Objec");
  464. changeMsig2("<S:Ljava/lang/Object;>(TS;[TS;)Ljava/lang/Objec;", "java/lang/Object",
  465. "<S:Ljava/lang/Object2;>(TS;[TS;)Ljava/lang/Objec;", "java/lang/Object2");
  466. String sig = "<T:Ljava/lang/Exception;>LPoi$Foo<Ljava/lang/String;>;LBar;LBar2;";
  467. String res = "<T:Ljava/lang/Exception;>LPoi$Foo<Ljava/lang/String2;>;LBar;LBar2;";
  468. changeMsig(sig, "java/lang/String", res, "java/lang/String2");
  469. changeMsig2(sig, "java/lang/String", res, "java/lang/String2");
  470. changeMsig("Ltest<TE;>.List;", "ist", "Ltest<TE;>.List;", "IST");
  471. changeMsig("Ljava/lang/String<Ljava/lang/Object;>;", "java/lang/String",
  472. "Ljava/lang/String2<Ljava/lang/Object;>;", "java/lang/String2");
  473. changeMsig2("Ljava/lang/String<Ljava/lang/Object;>;", "java/lang/String",
  474. "Ljava/lang/String2<Ljava/lang/Object;>;", "java/lang/String2");
  475. }
  476. private void changeMsig(String old, String oldname, String result, String newname) {
  477. String r = SignatureAttribute.renameClass(old, oldname, newname);
  478. assertEquals(result, r);
  479. }
  480. private void changeMsig2(String old, String oldname, String result, String newname) {
  481. ClassMap map = new ClassMap();
  482. map.put(oldname, newname);
  483. String r = SignatureAttribute.renameClass(old, map);
  484. assertEquals(result, r);
  485. }
  486. public void testSignatureEncode() throws Exception {
  487. BaseType bt = new BaseType("int");
  488. TypeVariable tv = new TypeVariable("S");
  489. ArrayType at = new ArrayType(1, tv);
  490. ClassType ct1 = new ClassType("test.Foo");
  491. TypeArgument ta = new TypeArgument();
  492. TypeArgument ta2 = new TypeArgument(ct1);
  493. TypeArgument ta3 = TypeArgument.subclassOf(ct1);
  494. ClassType ct2 = new ClassType("test.Foo", new TypeArgument[] { ta, ta2, ta3 });
  495. ClassType ct3 = new ClassType("test.Bar");
  496. ClassType ct4 = new ClassType("test.Bar", new TypeArgument[] { ta });
  497. NestedClassType ct5 = new NestedClassType(ct4, "Baz", new TypeArgument[] { ta });
  498. TypeParameter tp1 = new TypeParameter("U");
  499. TypeParameter tp2 = new TypeParameter("V", ct1, new ObjectType[] { ct3 });
  500. ClassSignature cs = new ClassSignature(new TypeParameter[] { tp1 },
  501. ct1,
  502. new ClassType[] { ct2 });
  503. MethodSignature ms = new MethodSignature(new TypeParameter[] { tp1, tp2 },
  504. new Type[] { bt, at, ct5 }, ct3,
  505. new ObjectType[] { ct1, tv });
  506. assertEquals("<U:Ljava/lang/Object;>Ltest/Foo;Ltest/Foo<*Ltest/Foo;+Ltest/Foo;>;",
  507. cs.encode());
  508. assertEquals("<U:Ljava/lang/Object;V:Ltest/Foo;:Ltest/Bar;>(I[TS;Ltest/Bar<*>$Baz<*>;)Ltest/Bar;^Ltest/Foo;^TS;",
  509. ms.encode());
  510. }
  511. public void testModifiers() throws Exception {
  512. CtClass c = loader.get("test3.Mods");
  513. c.setModifiers(Modifier.PROTECTED);
  514. assertEquals(AccessFlag.PROTECTED | AccessFlag.SUPER, c.getClassFile2().getAccessFlags());
  515. CtClass c2 = loader.get("test3.Mods2");
  516. c2.setModifiers(Modifier.PUBLIC | c2.getModifiers());
  517. assertEquals(AccessFlag.PUBLIC | AccessFlag.INTERFACE | AccessFlag.ABSTRACT,
  518. c2.getClassFile2().getAccessFlags());
  519. ClassFile cf = new ClassFile(false, "Test", null);
  520. assertEquals(AccessFlag.SUPER, cf.getAccessFlags());
  521. ClassFile cf2 = new ClassFile(true, "Test2", null);
  522. assertEquals(AccessFlag.INTERFACE | AccessFlag.ABSTRACT, cf2.getAccessFlags());
  523. }
  524. public void testByteStream() throws Exception {
  525. ByteStream bs = new ByteStream(16);
  526. ByteArrayOutputStream ba = new ByteArrayOutputStream();
  527. DataOutputStream dos = new DataOutputStream(ba);
  528. for (int i = 0; i < 100; i++) {
  529. bs.write(i);
  530. dos.write(i);
  531. bs.writeShort(i + 1);
  532. dos.writeShort(i + 1);
  533. bs.writeInt(i + 2);
  534. dos.writeInt(i + 2);
  535. bs.writeLong(i + 3);
  536. dos.writeLong(i + 3);
  537. }
  538. bs.writeLong(Long.MAX_VALUE);
  539. dos.writeLong(Long.MAX_VALUE);
  540. bs.writeFloat(Float.MAX_VALUE);
  541. dos.writeFloat(Float.MAX_VALUE);
  542. bs.writeDouble(Double.MAX_VALUE);
  543. dos.writeDouble(Double.MAX_VALUE);
  544. compare(bs, ba);
  545. }
  546. public void testByteStreamUtf() throws Exception {
  547. ByteStream bs = new ByteStream(4);
  548. ByteArrayOutputStream ba = new ByteArrayOutputStream();
  549. DataOutputStream dos = new DataOutputStream(ba);
  550. char c2 = '\u00b4';
  551. char c3 = '\u3007';
  552. bs.writeUTF("abc");
  553. dos.writeUTF("abc");
  554. String s = "" + c2 + c2;
  555. bs.writeUTF(s);
  556. dos.writeUTF(s);
  557. s = "" + c3 + c3;
  558. bs.writeUTF(s);
  559. dos.writeUTF(s);
  560. s = "abcdefgh" + c2 + "123" + c3 + "456";
  561. bs.writeUTF(s);
  562. dos.writeUTF(s);
  563. compare(bs, ba);
  564. }
  565. private void compare(ByteStream bs, ByteArrayOutputStream bos) {
  566. byte[] bs2 = bs.toByteArray();
  567. byte[] bos2 = bos.toByteArray();
  568. assertEquals(bs2.length, bos2.length);
  569. for (int i = 0; i < bs2.length; i++)
  570. assertEquals(bs2[i], bos2[i]);
  571. }
  572. public void testConstInfos() throws Exception {
  573. int n = 1;
  574. Utf8Info ui1 = new Utf8Info("test", n++);
  575. Utf8Info ui2 = new Utf8Info("te" + "st", n++);
  576. Utf8Info ui3 = new Utf8Info("test2", n++);
  577. assertTrue(ui1.hashCode() == ui2.hashCode());
  578. assertTrue(ui1.equals(ui1));
  579. assertTrue(ui1.equals(ui2));
  580. assertFalse(ui1.equals(ui3));
  581. assertFalse(ui1.equals(null));
  582. ClassInfo ci1 = new ClassInfo(ui1.index, n++);
  583. ClassInfo ci2 = new ClassInfo(ui1.index, n++);
  584. ClassInfo ci3 = new ClassInfo(ui2.index, n++);
  585. ClassInfo ci4 = new ClassInfo(ui3.index, n++);
  586. assertTrue(ci1.hashCode() == ci2.hashCode());
  587. assertTrue(ci1.equals(ci1));
  588. assertTrue(ci1.equals(ci2));
  589. assertFalse(ci1.equals(ci3));
  590. assertFalse(ci1.equals(ci4));
  591. assertFalse(ci1.equals(ui1));
  592. assertFalse(ci1.equals(null));
  593. NameAndTypeInfo ni1 = new NameAndTypeInfo(ui1.index, ui3.index, n++);
  594. NameAndTypeInfo ni2 = new NameAndTypeInfo(ui1.index, ui3.index, n++);
  595. NameAndTypeInfo ni3 = new NameAndTypeInfo(ui1.index, ui1.index, n++);
  596. NameAndTypeInfo ni4 = new NameAndTypeInfo(ui3.index, ui3.index, n++);
  597. assertTrue(ni1.hashCode() == ni2.hashCode());
  598. assertTrue(ni1.equals(ni1));
  599. assertTrue(ni1.equals(ni2));
  600. assertFalse(ni1.equals(ni3));
  601. assertFalse(ni1.equals(ni4));
  602. assertFalse(ni1.equals(ci1));
  603. assertFalse(ni1.equals(null));
  604. MethodrefInfo mi1 = new MethodrefInfo(ui1.index, ui3.index, n++);
  605. MethodrefInfo mi2 = new MethodrefInfo(ui1.index, ui3.index, n++);
  606. MethodrefInfo mi3 = new MethodrefInfo(ui1.index, ui1.index, n++);
  607. MethodrefInfo mi4 = new MethodrefInfo(ui2.index, ui3.index, n++);
  608. assertTrue(mi1.hashCode() == mi2.hashCode());
  609. assertTrue(mi1.equals(mi1));
  610. assertTrue(mi1.equals(mi2));
  611. assertFalse(mi1.equals(mi3));
  612. assertFalse(mi1.equals(mi4));
  613. assertFalse(mi1.equals(ci1));
  614. assertFalse(mi1.equals(null));
  615. FieldrefInfo field1 = new FieldrefInfo(ui1.index, ui3.index, n++);
  616. FieldrefInfo field2 = new FieldrefInfo(ui1.index, ui1.index, n++);
  617. FieldrefInfo field3 = new FieldrefInfo(ui1.index, ui1.index, n++);
  618. InterfaceMethodrefInfo intf1 = new InterfaceMethodrefInfo(ui1.index, ui3.index, n++);
  619. InterfaceMethodrefInfo intf2 = new InterfaceMethodrefInfo(ui1.index, ui3.index, n++);
  620. assertFalse(mi1.equals(field1));
  621. assertFalse(field1.equals(mi1));
  622. assertTrue(field2.equals(field3));
  623. assertFalse(mi1.equals(field2));
  624. assertFalse(mi1.equals(intf1));
  625. assertFalse(intf1.equals(mi1));
  626. assertTrue(intf1.equals(intf2));
  627. StringInfo si1 = new StringInfo(ui1.index, n++);
  628. StringInfo si2 = new StringInfo(ui1.index, n++);
  629. StringInfo si3 = new StringInfo(ui2.index, n++);
  630. assertTrue(si1.hashCode() == si2.hashCode());
  631. assertTrue(si1.equals(si1));
  632. assertTrue(si1.equals(si2));
  633. assertFalse(si1.equals(si3));
  634. assertFalse(si1.equals(ci1));
  635. assertFalse(si1.equals(null));
  636. IntegerInfo ii1 = new IntegerInfo(12345, n++);
  637. IntegerInfo ii2 = new IntegerInfo(12345, n++);
  638. IntegerInfo ii3 = new IntegerInfo(-12345, n++);
  639. assertTrue(ii1.hashCode() == ii2.hashCode());
  640. assertTrue(ii1.equals(ii1));
  641. assertTrue(ii1.equals(ii2));
  642. assertFalse(ii1.equals(ii3));
  643. assertFalse(ii1.equals(ci1));
  644. assertFalse(ii1.equals(null));
  645. FloatInfo fi1 = new FloatInfo(12345.0F, n++);
  646. FloatInfo fi2 = new FloatInfo(12345.0F, n++);
  647. FloatInfo fi3 = new FloatInfo(-12345.0F, n++);
  648. assertTrue(fi1.hashCode() == fi2.hashCode());
  649. assertTrue(fi1.equals(fi1));
  650. assertTrue(fi1.equals(fi2));
  651. assertFalse(fi1.equals(fi3));
  652. assertFalse(fi1.equals(ci1));
  653. assertFalse(fi1.equals(null));
  654. LongInfo li1 = new LongInfo(12345L, n++);
  655. LongInfo li2 = new LongInfo(12345L, n++);
  656. LongInfo li3 = new LongInfo(-12345L, n++);
  657. assertTrue(li1.hashCode() == li2.hashCode());
  658. assertTrue(li1.equals(li1));
  659. assertTrue(li1.equals(li2));
  660. assertFalse(li1.equals(li3));
  661. assertFalse(li1.equals(ci1));
  662. assertFalse(li1.equals(null));
  663. DoubleInfo di1 = new DoubleInfo(12345.0, n++);
  664. DoubleInfo di2 = new DoubleInfo(12345.0, n++);
  665. DoubleInfo di3 = new DoubleInfo(-12345.0, n++);
  666. assertTrue(di1.hashCode() == di2.hashCode());
  667. assertTrue(di1.equals(di1));
  668. assertTrue(di1.equals(di2));
  669. assertFalse(di1.equals(di3));
  670. assertFalse(di1.equals(ci1));
  671. assertFalse(di1.equals(null));
  672. }
  673. public void testConstInfoAdd() {
  674. ConstPool cp = new ConstPool("test.Tester");
  675. assertEquals("test.Tester", cp.getClassName());
  676. int n0 = cp.addClassInfo("test.Foo");
  677. assertEquals(n0, cp.addClassInfo("test.Foo"));
  678. int n1 = cp.addUtf8Info("test.Bar");
  679. assertEquals(n1, cp.addUtf8Info("test.Bar"));
  680. int n2 = cp.addUtf8Info("()V");
  681. assertEquals(n2, cp.addUtf8Info("()V"));
  682. assertTrue(n1 != n2);
  683. int n3 = cp.addNameAndTypeInfo(n1, n2);
  684. assertEquals(n3, cp.addNameAndTypeInfo(n1, n2));
  685. assertEquals(n3, cp.addNameAndTypeInfo("test.Bar", "()V"));
  686. int n4 = cp.addNameAndTypeInfo("test.Baz", "()V");
  687. assertTrue(n3 != n4);
  688. assertTrue(n3 != cp.addNameAndTypeInfo(cp.addUtf8Info("test.Baz"), n2));
  689. int n5 = cp.addFieldrefInfo(n0, n3);
  690. assertEquals(n5, cp.addFieldrefInfo(n0, n3));
  691. assertTrue(n5 != cp.addFieldrefInfo(n0, n4));
  692. assertTrue(cp.addMethodrefInfo(n0, n3) == cp.addMethodrefInfo(n0, n3));
  693. assertTrue(cp.addMethodrefInfo(n0, "test", "()B") == cp.addMethodrefInfo(n0, "test", "()B"));
  694. assertTrue(cp.addMethodrefInfo(n0, "test", "()B") != cp.addMethodrefInfo(n0, "test", "()I"));
  695. assertTrue(n5 != cp.addInterfaceMethodrefInfo(n0, n3));
  696. assertTrue(cp.addInterfaceMethodrefInfo(n0, "test", "()B")
  697. == cp.addInterfaceMethodrefInfo(n0, "test", "()B"));
  698. assertTrue(cp.addInterfaceMethodrefInfo(n0, "test", "()B")
  699. != cp.addInterfaceMethodrefInfo(n0, "test", "()I"));
  700. int n6 = cp.addStringInfo("foobar");
  701. assertEquals(n6, cp.addStringInfo("foobar"));
  702. assertTrue(n6 != cp.addStringInfo("foobar2"));
  703. int n7 = cp.addIntegerInfo(123);
  704. assertEquals(n7, cp.addIntegerInfo(123));
  705. assertTrue(n7 != cp.addIntegerInfo(-123));
  706. int n8 = cp.addFloatInfo(123);
  707. assertEquals(n8, cp.addFloatInfo(123.0F));
  708. assertTrue(n8 != cp.addFloatInfo(-123.0F));
  709. int n9 = cp.addLongInfo(1234L);
  710. assertEquals(n9, cp.addLongInfo(1234L));
  711. assertTrue(n9 != cp.addLongInfo(-1234L));
  712. int n10 = cp.addDoubleInfo(1234.0);
  713. assertEquals(n10, cp.addDoubleInfo(1234.0));
  714. assertTrue(n10 != cp.addDoubleInfo(-1234.0));
  715. cp.prune();
  716. assertEquals(n1, cp.addUtf8Info("test.Bar"));
  717. assertEquals(n0, cp.addClassInfo("test.Foo"));
  718. assertEquals(n10, cp.addDoubleInfo(1234.0));
  719. }
  720. public void testRenameInConstPool() {
  721. ConstPool cp = new ConstPool("test.Tester");
  722. int n1 = cp.addClassInfo("test.Foo");
  723. int n2 = cp.addClassInfo("test.Bar");
  724. int n3 = cp.addClassInfo("test.Baz");
  725. int n4 = cp.addNameAndTypeInfo("foo", "(Ltest/Foo;)V");
  726. int n5 = cp.addNameAndTypeInfo("bar", "(Ltest/Bar;)V");
  727. int n6 = cp.addNameAndTypeInfo("baz", "(Ltest/Baz;)V");
  728. int n7 = cp.addClassInfo("[Ltest/Foo;");
  729. int n8 = cp.addClassInfo("[Ltest/Bar;");
  730. cp.renameClass("test/Foo", "test/Foo2");
  731. assertEquals("test.Foo2", cp.getClassInfo(n1));
  732. assertEquals("(Ltest/Foo2;)V", cp.getUtf8Info(cp.getNameAndTypeDescriptor(n4)));
  733. assertTrue(cp.addClassInfo("test.Foo2") == n1);
  734. assertTrue(cp.addClassInfo("test.Foo") != n1);
  735. assertTrue(cp.addNameAndTypeInfo("foo", "(Ltest/Foo2;)V") == n4);
  736. assertTrue(cp.addNameAndTypeInfo("foo", "(Ltest/Foo;)V") != n4);
  737. assertEquals("[Ltest.Foo2;", cp.getClassInfo(n7));
  738. ClassMap map = new ClassMap();
  739. map.put("test.Bar", "test.Bar2");
  740. map.put("test.Baz", "test.Baz2");
  741. cp.renameClass(map);
  742. assertEquals("test.Bar2", cp.getClassInfo(n2));
  743. assertEquals("(Ltest/Bar2;)V", cp.getUtf8Info(cp.getNameAndTypeDescriptor(n5)));
  744. assertTrue(cp.addClassInfo("test.Bar2") == n2);
  745. assertTrue(cp.addClassInfo("test.Bar") != n2);
  746. assertTrue(cp.addNameAndTypeInfo("bar", "(Ltest/Bar2;)V") == n5);
  747. assertTrue(cp.addNameAndTypeInfo("bar", "(Ltest/Bar;)V") != n5);
  748. assertEquals("[Ltest.Bar2;", cp.getClassInfo(n8));
  749. }
  750. public void testInvokeDynamic() throws Exception {
  751. CtClass cc = loader.get("test4.InvokeDyn");
  752. ClassFile cf = cc.getClassFile();
  753. ConstPool cp = cf.getConstPool();
  754. Bytecode code = new Bytecode(cp, 0, 1);
  755. code.addAload(0);
  756. code.addIconst(9);
  757. code.addLdc("nine");
  758. code.addInvokedynamic(0, "call", "(ILjava/lang/String;)I");
  759. code.addOpcode(Opcode.SWAP);
  760. code.addOpcode(Opcode.POP);
  761. code.addOpcode(Opcode.IRETURN);
  762. MethodInfo minfo = new MethodInfo(cp, "test", "()I");
  763. minfo.setCodeAttribute(code.toCodeAttribute());
  764. minfo.setAccessFlags(AccessFlag.PUBLIC);
  765. minfo.rebuildStackMapIf6(loader, cf);
  766. cf.addMethod(minfo);
  767. cf.addMethod(new MethodInfo(cp, "test2", minfo, null));
  768. int mtIndex = cp.addMethodTypeInfo(cp.addUtf8Info("(I)V"));
  769. String desc
  770. = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)" +
  771. "Ljava/lang/invoke/CallSite;";
  772. int mri = cp.addMethodrefInfo(cp.addClassInfo(cc.getName()), "boot", desc);
  773. int mhi = cp.addMethodHandleInfo(ConstPool.REF_invokeStatic, mri);
  774. int[] args = new int[0];
  775. BootstrapMethodsAttribute.BootstrapMethod[] bms
  776. = new BootstrapMethodsAttribute.BootstrapMethod[1];
  777. bms[0] = new BootstrapMethodsAttribute.BootstrapMethod(mhi, args);
  778. cf.addAttribute(new BootstrapMethodsAttribute(cp, bms));
  779. cc.writeFile();
  780. Object obj = make(cc.getName());
  781. assertEquals(9, invoke(obj, "test"));
  782. ClassPool cp2 = new ClassPool();
  783. cp2.appendClassPath(".");
  784. CtClass cc2 = cp2.get(cc.getName());
  785. assertEquals("test4.InvokeDyn", cc2.getClassFile().getName());
  786. ConstPool cPool2 = cc2.getClassFile().getConstPool();
  787. assertEquals("(I)V", cPool2.getUtf8Info(cPool2.getMethodTypeInfo(mtIndex)));
  788. }
  789. public static Test suite() {
  790. TestSuite suite = new TestSuite("Bytecode Tests");
  791. suite.addTestSuite(BytecodeTest.class);
  792. return suite;
  793. }
  794. }