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