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