Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javassist.CannotCompileException: [source error] no such field: $1

Referring to : http://jboss-javassist.github.io/javassist/tutorial/tutorial2.html

method.insertBefore("{ System.out.println($1);}");

This statement gives me following error:

Exception: javassist.CannotCompileException: [source error] no such field: $1
javassist.CannotCompileException: [source error] no such field: $1
        at javassist.CtBehavior.insertBefore(CtBehavior.java:774)
        at javassist.CtBehavior.insertBefore(CtBehavior.java:734)
        at com.here.debugHelper.DurationTransformer.transform(DurationTransformer.java:124)
        at sun.instrument.TransformerManager.transform(Unknown Source)
        at sun.instrument.InstrumentationImpl.transform(Unknown Source)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at com.here.debugHelper.TestInstrumentation.main(TestInstrumentation.java:10)
Caused by: compile error: no such field: $1
        at javassist.compiler.TypeChecker.fieldAccess(TypeChecker.java:845)
        at javassist.compiler.TypeChecker.atFieldRead(TypeChecker.java:803)
        at javassist.compiler.TypeChecker.atMember(TypeChecker.java:988)
        at javassist.compiler.JvstTypeChecker.atMember(JvstTypeChecker.java:66)
        at javassist.compiler.ast.Member.accept(Member.java:39)
        at javassist.compiler.JvstTypeChecker.atMethodArgs(JvstTypeChecker.java:221)
        at javassist.compiler.TypeChecker.atMethodCallCore(TypeChecker.java:735)
        at javassist.compiler.TypeChecker.atCallExpr(TypeChecker.java:695)
        at   javassist.compiler.JvstTypeChecker.atCallExpr(JvstTypeChecker.java:157)
        at javassist.compiler.ast.CallExpr.accept(CallExpr.java:46)
        at javassist.compiler.CodeGen.doTypeCheck(CodeGen.java:242)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:330)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:351)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
        at javassist.compiler.Javac.compileStmnt(Javac.java:567)
        at javassist.CtBehavior.insertBefore(CtBehavior.java:754)
        ... 17 more

Moreover,the same error appears when I use any parameter(passed to the parameter) or any local variable instead of '$1'. This has been covered in this question, but I don't really understand the solution there.

There is this other post with same question but no answer.

Please help. Thank you

like image 774
Gautam Avatar asked Mar 02 '17 09:03

Gautam


1 Answers

Alright, this is how I worked around the problem. There were few mistakes that I was overlooking and some things that I learnt. I am sharing this since I could not find the content directly addressing the issue anywhere. Referring to this answer and this article:

The insertBefore, insertAfter and other such methods cannot access any local variable but can access method parameter of the method by their names. no such field error occurs if attempt is made to access local variable.

These methods cannot access any parameter declared within them as a process of instrumentation. ctmethod.insertBefore("{int i = 4; int j = 9;}") ctmethod.insertBefore("i = 5;"); ctMethod.insertAfter("j = 9;");

  • The above code will give no such field: j(and i) error
  • insertBefore, insertAfter, expect a single statement, or a single block of code as done in first line of above code snippet.
  • This error no such field appears in case when variables are used in ctmethod.addcatch() too.
  • ctmethod.addLocalVariable() helps in declaring a variable that can be accessed by insertBefore(), etc. However, .addCatch() will still give no such field error if you try to use variable declared using .addLocalVariable()
  • I was getting no such field: $1 due to my silly mistake. I was going iterating through a number of method in a class, so the error was due to the fact that some of those methods had zero arguments. $1,$2.. and $args work well as explained in this doc.

P.S. I will add further tips as I come across them and any corrections are welcomed.

like image 97
Gautam Avatar answered Sep 28 '22 06:09

Gautam