package javassist; import java.lang.annotation.Annotation; import java.lang.reflect.TypeVariable; import javassist.bytecode.AccessFlag; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.AttributeInfo; import javassist.bytecode.ClassFile; import javassist.bytecode.ConstPool; import javassist.bytecode.InnerClassesAttribute; import javassist.bytecode.NestHostAttribute; import javassist.bytecode.NestMembersAttribute; import javassist.expr.ExprEditor; import javassist.expr.Handler; import javassist.expr.MethodCall; @SuppressWarnings({"rawtypes","unchecked","unused"}) public class JvstTest5 extends JvstTestRoot { public JvstTest5(String name) { super(name); } public void testDollarClassInStaticMethod() throws Exception { CtClass cc = sloader.makeClass("test5.DollarClass"); CtMethod m = CtNewMethod.make("public static int run(){ return $class.getName().length(); }", cc); cc.addMethod(m); m = CtNewMethod.make("public int run2(){ return $class.getName().length(); }", cc); cc.addMethod(m); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(cc.getName().length(), invoke(obj, "run")); assertEquals(cc.getName().length(), invoke(obj, "run2")); } public void testSuperDefaultMethodCall() throws Exception { CtClass cc = sloader.get("test5.DefaultMethod"); CtMethod m = CtNewMethod.make("public int run(){ return test5.DefaultMethodIntf.super.foo(); }", cc); cc.addMethod(m); m = CtNewMethod.make("public int run2(){ return test5.DefaultMethodIntf.baz(); }", cc); cc.addMethod(m); m = CtNewMethod.make("public int run3(){ return test5.DefaultMethodIntf.super.baz(); }", cc); cc.addMethod(m); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(1, invoke(obj, "run")); assertEquals(10, invoke(obj, "run2")); assertEquals(10, invoke(obj, "run3")); } public void testTypeAnno() throws Exception { CtClass cc = sloader.get("test5.TypeAnno"); cc.getClassFile().compact(); cc.writeFile(); Object obj = make(cc.getName()); TypeVariable t = obj.getClass().getTypeParameters()[0]; Annotation[] annos = t.getAnnotations(); assertEquals("@test5.TypeAnnoA()", annos[0].toString()); } public void testJIRA241() throws Exception { CtClass cc = sloader.get("test5.JIRA241"); CtMethod testMethod = cc.getDeclaredMethod("test"); testMethod.insertAfter("System.out.println(\"inserted!\");"); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(10, invoke(obj, "run")); } public void testJIRA246() throws Exception { CtClass ctClass = sloader.makeClass("test5.JIRA246Test"); ctClass.addInterface(sloader.get(test5.JIRA246.Test.class.getName())); String methodBody = "public void test() { defaultMethod(); }"; CtMethod ctMethod = CtMethod.make(methodBody, ctClass); ctClass.addMethod(ctMethod); } public void testJIRA246b() throws Exception { CtClass ctClass = sloader.get(test5.JIRA246.A.class.getName()); String src = "public void id() { get(); }"; CtMethod make = CtNewMethod.make(src, ctClass); } public void testJIRA242() throws Exception { Boolean ss = Boolean.valueOf(2 > 3); ClassPool cp = ClassPool.getDefault(); CtClass cc = cp.get("test5.JIRA242$Hello"); CtMethod m = cc.getDeclaredMethod("say"); m.insertBefore("{ System.out.println(\"Say Hello...\"); }"); StringBuilder sb = new StringBuilder(); sb.append("BOOL_SERIES = createBooleanSeriesStep();"); //Below code cause the issue sb.append("BOOL_SERIES.setValue(3>=3);"); //lets comment this and run it will work // Below code snippets will work // this cast into exact class and call the same function sb.append("((test5.JIRA242$BooleanDataSeries)BOOL_SERIES).setValue(3>=3);"); // this code snippet will set exact boolean variable to the function. sb.append("boolean var = 3>=3;"); sb.append("BOOL_SERIES.setValue(var);"); m.insertBefore(sb.toString()); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(0, invoke(obj, "say")); } public void testJIRA249() throws Exception { CtClass cc = sloader.get("test5.BoolTest"); CtMethod testMethod = cc.getDeclaredMethod("test"); testMethod.insertBefore("i = foo(true & true);"); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(1, invoke(obj, "run")); } public void testInnerClassAttributeRemove() throws Exception { CtClass cc = sloader.get("test5.InnerClassRemove"); ClassFile cf = cc.getClassFile(); InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute(InnerClassesAttribute.tag); String second = ica.innerClass(1); String secondName = ica.innerName(1); String third = ica.innerClass(2); String thirdName = ica.innerName(2); assertEquals(3, ica.remove(3)); assertEquals(2, ica.remove(0)); assertEquals(second, ica.innerClass(0)); assertEquals(secondName, ica.innerName(0)); assertEquals(third, ica.innerClass(1)); assertEquals(thirdName, ica.innerName(1)); assertEquals(1, ica.remove(1)); assertEquals(second, ica.innerClass(0)); assertEquals(secondName, ica.innerName(0)); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(1, invoke(obj, "run")); } public void testJIRA248() throws Exception { CtClass cc = sloader.get("test5.JIRA248"); String methodBody = "public int run() { return foo() + super.foo() + super.bar() + test5.JIRA248Intf2.super.baz(); }"; CtMethod ctMethod = CtMethod.make(methodBody, cc); cc.addMethod(ctMethod); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(40271, invoke(obj, "run")); } public void testInvalidCastWithDollar() throws Exception { String code = "{ new test5.JavassistInvalidCastTest().inspectReturn((Object) ($w) $_); } "; CtClass c = sloader.get("test5.InvalidCastDollar"); for (CtMethod method : c.getDeclaredMethods()) method.insertAfter(code); } public void testJIRA256() throws Exception { // CtClass ec = sloader.get("test5.Entity"); CtClass cc = sloader.makeClass("test5.JIRA256"); ClassFile ccFile = cc.getClassFile(); ConstPool constpool = ccFile.getConstPool(); AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag); javassist.bytecode.annotation.Annotation entityAnno = new javassist.bytecode.annotation.Annotation("test5.Entity", constpool); // = new javassist.bytecode.annotation.Annotation(constpool, ec); entityAnno.addMemberValue("value", new javassist.bytecode.annotation.ArrayMemberValue(constpool)); attr.addAnnotation(entityAnno); ccFile.addAttribute(attr); cc.writeFile(); Object o = make(cc.getName()); assertTrue(o.getClass().getName().equals("test5.JIRA256")); java.lang.annotation.Annotation[] annotations = o.getClass().getDeclaredAnnotations(); assertEquals(1, annotations.length); } public void testJIRA250() throws Exception { CtClass cc = sloader.makeClass("test5.JIRA250", sloader.get("test5.JIRA250Super")); cc.addMethod(CtNewMethod.make( " public test5.JIRA250Bar getBar() {" + " return super.getBar();\n" + " }\n", cc)); cc.addMethod(CtNewMethod.make("public int run() { getBar(); return 1; }", cc)); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(1, invoke(obj, "run")); } public void testProceedToDefaultMethod() throws Exception { CtClass cc = ClassPool.getDefault().get("test5.ProceedDefault"); CtMethod mth = cc.getDeclaredMethod("bar"); mth.instrument(new ExprEditor() { public void edit(MethodCall c) throws CannotCompileException { c.replace("$_ = $proceed($$) + 10000;"); } }); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(21713, invoke(obj, "run")); } public void testBadClass() throws Exception { CtClass badClass = ClassPool.getDefault().makeClass("badClass"); String src = String.join(System.getProperty("line.separator"), "public void eval () {", " if (true) {", " double t=0;", " } else {", " double t=0;", " }", " for (int i=0; i < 2; i++) {", " int a=0;", " int b=0;", " int c=0;", " int d=0;", " if (true) {", " int e = 0;", " }", " }", "}"); System.out.println(src); badClass.addMethod(CtMethod.make(src, badClass)); Class clazzz = badClass.toClass(Class.forName("DefineClassCapability")); Object obj = clazzz.getConstructor().newInstance(); // <-- falls here } public void test83StackmapWithArrayType() throws Exception { final CtClass ctClass = sloader.get("test5.StackmapWithArray83"); final CtMethod method = ctClass.getDeclaredMethod("bytecodeVerifyError"); method.addLocalVariable("test_localVariable", CtClass.intType); method.insertBefore("{ test_localVariable = 1; }"); final CtMethod method2 = ctClass.getDeclaredMethod("bytecodeVerifyError2"); method2.addLocalVariable("test_localVariable", CtClass.intType); method2.insertBefore("{ test_localVariable = 1; }"); ctClass.writeFile(); Object obj = make(ctClass.getName()); assertEquals(1, invoke(obj, "run")); } public void testLoaderClassPath() throws Exception { ClassPool cp = new ClassPool(); cp.appendClassPath(new LoaderClassPath(new Loader())); assertNotNull(cp.get(Object.class.getName())); assertNotNull(cp.get(this.getClass().getName())); } public void testAddDefaultMethod() throws Exception { CtClass cc = sloader.makeInterface("test5.AddDefaultMethod"); cc.addMethod(CtNewMethod.make("static int foo() { return 1; }", cc)); cc.addMethod(CtNewMethod.make("public static int foo1() { return 1; }", cc)); cc.addMethod(CtNewMethod.make("public int foo2() { return 1; }", cc)); cc.addMethod(CtNewMethod.make("int foo3() { return 1; }", cc)); try { cc.addMethod(CtNewMethod.make("private int foo4() { return 1; }", cc)); fail(); } catch (CannotCompileException e) {} try { cc.addMethod(CtNewMethod.make("private static int foo5() { return 1; }", cc)); fail(); } catch (CannotCompileException e) {} } public void testRemoveAnnotatino() throws Exception { CtClass cc = sloader.get("test5.RemoveAnnotation"); AnnotationsAttribute aa = (AnnotationsAttribute)cc.getClassFile().getAttribute(AnnotationsAttribute.invisibleTag); assertTrue(aa.removeAnnotation("test5.RemoveAnno1")); AttributeInfo ai = cc.getClassFile().removeAttribute(AnnotationsAttribute.invisibleTag); assertEquals(ai.getName(), AnnotationsAttribute.invisibleTag); CtMethod foo = cc.getDeclaredMethod("foo"); AnnotationsAttribute aa2 = (AnnotationsAttribute)foo.getMethodInfo().getAttribute(AnnotationsAttribute.invisibleTag); assertTrue(aa2.removeAnnotation("test5.RemoveAnno1")); CtMethod bar = cc.getDeclaredMethod("bar"); AnnotationsAttribute aa3 = (AnnotationsAttribute)bar.getMethodInfo().getAttribute(AnnotationsAttribute.invisibleTag); assertFalse(aa3.removeAnnotation("test5.RemoveAnno1")); assertTrue(aa3.removeAnnotation("test5.RemoveAnno2")); AttributeInfo ai2 = bar.getMethodInfo().removeAttribute(AnnotationsAttribute.invisibleTag); assertEquals(ai2.getName(), AnnotationsAttribute.invisibleTag); CtMethod run = cc.getDeclaredMethod("run"); AttributeInfo ai3 = run.getMethodInfo().removeAttribute(AnnotationsAttribute.invisibleTag); assertNull(ai3); CtField baz = cc.getDeclaredField("baz"); AttributeInfo ai4 = baz.getFieldInfo().removeAttribute(AnnotationsAttribute.invisibleTag); assertEquals(ai4.getName(), AnnotationsAttribute.invisibleTag); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(3, invoke(obj, "run")); } public void testInnerClassModifiers() throws Exception { CtClass cc = sloader.get("test5.InnerModifier$NonStatic"); try { cc.setModifiers(Modifier.PUBLIC | Modifier.STATIC); fail(); } catch (RuntimeException e) { if (!e.getMessage().startsWith("cannot change ")) fail(); } cc.setModifiers(Modifier.PUBLIC); cc.writeFile(); assertEquals(Modifier.PUBLIC, cc.getModifiers()); InnerClassesAttribute ica = getInnerClassAttr(cc); int i = ica.find("test5.InnerModifier$NonStatic"); assertTrue(i >= 0); assertEquals(Modifier.PUBLIC, ica.accessFlags(i)); CtClass cc2 = sloader.get("test5.InnerModifier$Static"); InnerClassesAttribute ica3 = getInnerClassAttr(cc2); int i3 = ica3.find("test5.InnerModifier$Static"); assertTrue(i3 >= 0); assertEquals(AccessFlag.STATIC, ica3.accessFlags(i3)); cc2.setModifiers(Modifier.PROTECTED | Modifier.STATIC); cc2.setModifiers(Modifier.PUBLIC); cc2.writeFile(); assertEquals(Modifier.PUBLIC | Modifier.STATIC, cc2.getModifiers()); InnerClassesAttribute ica2 = getInnerClassAttr(cc2); int i2 = ica2.find("test5.InnerModifier$Static"); assertTrue(i2 >= 0); assertEquals(AccessFlag.PUBLIC | AccessFlag.STATIC, ica2.accessFlags(i2)); CtClass cc3 = cc.getDeclaringClass(); assertTrue(cc3.isModified()); cc3.writeFile(); InnerClassesAttribute ica4 = getInnerClassAttr(cc3); int i4 = ica4.find("test5.InnerModifier$Static"); assertTrue(i4 >= 0); assertEquals(AccessFlag.PUBLIC | AccessFlag.STATIC, ica4.accessFlags(i4)); int i5 = ica4.find("test5.InnerModifier$NonStatic"); assertTrue(i5 >= 0); assertEquals(Modifier.PUBLIC, ica4.accessFlags(i5)); } public void testInnerClassModifiers2() throws Exception { CtClass cc = sloader.get("test5.InnerModifier2$Protected"); Class ccc = Class.forName("test5.InnerModifier2$Protected"); assertEquals(cc.getModifiers(), ccc.getModifiers()); assertTrue(Modifier.isProtected(cc.getModifiers())); cc = sloader.get("test5.InnerModifier2$Public"); ccc = Class.forName("test5.InnerModifier2$Public"); assertEquals(cc.getModifiers(), ccc.getModifiers()); assertTrue(Modifier.isPublic(cc.getModifiers())); cc = sloader.get("test5.InnerModifier2$Private"); ccc = Class.forName("test5.InnerModifier2$Private"); assertEquals(cc.getModifiers(), ccc.getModifiers()); assertTrue(Modifier.isPrivate(cc.getModifiers())); cc = sloader.get("test5.InnerModifier2$Package"); ccc = Class.forName("test5.InnerModifier2$Package"); assertEquals(cc.getModifiers(), ccc.getModifiers()); assertTrue(Modifier.isPackage(cc.getModifiers())); cc = sloader.get("test5.InnerModifier2$ProtectedStatic"); ccc = Class.forName("test5.InnerModifier2$ProtectedStatic"); assertEquals(cc.getModifiers(), ccc.getModifiers()); assertTrue(Modifier.isProtected(cc.getModifiers())); assertTrue(Modifier.isStatic(cc.getModifiers())); cc = sloader.get("test5.InnerModifier2$PublicStatic"); ccc = Class.forName("test5.InnerModifier2$PublicStatic"); assertEquals(cc.getModifiers(), ccc.getModifiers()); assertTrue(Modifier.isPublic(cc.getModifiers())); assertTrue(Modifier.isStatic(cc.getModifiers())); cc = sloader.get("test5.InnerModifier2$PrivateStatic"); ccc = Class.forName("test5.InnerModifier2$PrivateStatic"); assertEquals(cc.getModifiers(), ccc.getModifiers()); assertTrue(Modifier.isPrivate(cc.getModifiers())); assertTrue(Modifier.isStatic(cc.getModifiers())); cc = sloader.get("test5.InnerModifier2$PackageStatic"); ccc = Class.forName("test5.InnerModifier2$PackageStatic"); assertEquals(cc.getModifiers(), ccc.getModifiers()); assertTrue(Modifier.isPackage(cc.getModifiers())); assertTrue(Modifier.isStatic(cc.getModifiers())); } private InnerClassesAttribute getInnerClassAttr(CtClass cc) { return (InnerClassesAttribute)cc.getClassFile2().getAttribute(InnerClassesAttribute.tag); } public void testVarArgsModifier() throws Exception { CtClass cc = sloader.get("test5.VarArgsMethod"); assertTrue(Modifier.isVarArgs(cc.getDeclaredMethod("foo").getModifiers())); assertFalse(Modifier.isVarArgs(cc.getDeclaredMethod("bar").getModifiers())); } public void testIssue155() throws Exception { CtClass cc = sloader.get("test5.Issue155"); CtMethod testMethod = cc.getDeclaredMethod("foo"); testMethod.instrument( new ExprEditor() { public void edit(Handler m) throws CannotCompileException { m.insertBefore("throw $1;"); } }); cc.writeFile(); Object obj = make(cc.getName()); assertEquals(1, invoke(obj, "test")); } public void testNestHostAttribute() throws Exception { CtClass cc = sloader.get("test5.NestHost$Foo"); ClassFile cf = cc.getClassFile(); NestHostAttribute attr = (NestHostAttribute)cf.getAttribute(NestHostAttribute.tag); assertEquals(test5.NestHost.class.getName(), cf.getConstPool().getClassInfo(attr.hostClassIndex())); } public void testNestMembersAttribute() throws Exception { CtClass cc = sloader.get("test5.NestHost"); ClassFile cf = cc.getClassFile(); NestMembersAttribute attr = (NestMembersAttribute)cf.getAttribute(NestMembersAttribute.tag); assertEquals(2, attr.numberOfClasses()); String[] names = new String[2]; for (int i = 0; i < 2; i++) names[i] = cf.getConstPool().getClassInfo(attr.memberClass(i)); assertFalse(names[0].equals(names[1])); assertTrue(names[0].equals("test5.NestHost$Foo") || names[0].equals("test5.NestHost$Bar")); assertTrue(names[1].equals("test5.NestHost$Foo") || names[1].equals("test5.NestHost$Bar")); } public void testNestMembersAttributeCopy() throws Exception { CtClass cc = sloader.get("test5.NestHost2"); cc.getClassFile().compact(); cc.writeFile(); make(cc.getName()); } public void testNestHostAttributeCopy() throws Exception { CtClass cc = sloader.get("test5.NestHost2$Foo"); cc.getClassFile().compact(); cc.toClass(test5.DefineClassCapability.class); } }