Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception thrown when "insertBefore" a return expression #241

Open
tangzhenhuang opened this issue Jan 21, 2019 · 6 comments
Open

Exception thrown when "insertBefore" a return expression #241

tangzhenhuang opened this issue Jan 21, 2019 · 6 comments

Comments

@tangzhenhuang
Copy link

tangzhenhuang commented Jan 21, 2019

Recently, I am doing a mock function on methods, one of which is to modify the bytecode before the method starts. I inserted the following code with the insertBefore method:

        "{" +
            "if (!isRecord()) {" +
            "   return getMockData(\"%s\", $args, $type);" +
            "} "
        "}";

Among them, the definition of the getMockData method is:

/**
     * Get mock data
     *
     * @param uniqueMethodName The name of the method
     * @param args The arguments of the method
     * @param <T> The result type of the method
     * @return return mock data
     * @throws java.lang.Throwable
     */
public static <T> T getMockData(String uniqueMethodName, Object[] args, Class<T> clazz) throws Throwable;

But when it started, it throws the following exceptions:

Exception in thread "main" java.lang.VerifyError: Bad return type
Exception Details:
  Location:
    AnotherPluginTest.test()I @20: areturn
  Reason:
    Type 'java/lang/Object' (current frame, stack[0]) is not assignable to integer (from method signature)
  Current Frame:
    bci: @20
    flags: { }
    locals: { }
    stack: { 'java/lang/Object' }
  Bytecode:
    0x0000000: b800 d99a 0012 12d0 03bd 0006 12da b800
    0x0000010: e0b8 00e2 b004 b800 e4b2 0002 1203 b600
    0x0000020: 0404 a700 104b 12d0 03bd 0006 2ab8 00d2
    0x0000030: 2abf 3d12 d003 bd00 061c bb00 d459 5d58
    0x0000040: b700 d6b8 00d8 1cac                    
  Exception Handler Table:
    bci [25, 37] => handler: 37
  Stackmap Table:
    same_frame(@21)
    same_locals_1_stack_item_frame(@37,Object[#36])
    same_locals_1_stack_item_frame(@50,Integer)

	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)

When I delete the "insertBefore" expression, it was normal again. So I believe there are some problems with this statement("insertBefore" with return expression).

Thanks.

@chibash
Copy link
Member

chibash commented Jan 23, 2019

The type parameter T is java.lang.Object at the byte code level.
So you must insert explicit type cast before getMockData().

@tangzhenhuang
Copy link
Author

But when I changed the code to:

        "{" +
            "if (!isRecord()) {" +
            "   return ($r)getMockData(\"%s\", $args, $type);" +
            "} "
        "}";

It throws the following exception, doesn't $r work?

Caused by: javassist.CannotCompileException: [source error] no such class: $r
	at javassist.CtBehavior.insertBefore(CtBehavior.java:774)
	at javassist.CtBehavior.insertBefore(CtBehavior.java:734)
	at com.seewo.honeycomb.ttm.agent.bytecode.EMethod.insertBefore(EMethod.java:27)
	... 48 more
Caused by: compile error: no such class: $r
	at javassist.compiler.MemberResolver.searchImports(MemberResolver.java:468)
	at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:412)
	at javassist.compiler.MemberResolver.lookupClassByName(MemberResolver.java:315)
	at javassist.compiler.MemberResolver.resolveClassName(MemberResolver.java:502)
	at javassist.compiler.TypeChecker.resolveClassName(TypeChecker.java:132)
	at javassist.compiler.TypeChecker.atCastExpr(TypeChecker.java:546)
	at javassist.compiler.JvstTypeChecker.atCastExpr(JvstTypeChecker.java:104)
	at javassist.compiler.ast.CastExpr.accept(CastExpr.java:55)
	at javassist.compiler.CodeGen.doTypeCheck(CodeGen.java:242)
	at javassist.compiler.CodeGen.compileExpr(CodeGen.java:229)
	at javassist.compiler.CodeGen.atReturnStmnt2(CodeGen.java:615)
	at javassist.compiler.JvstCodeGen.atReturnStmnt(JvstCodeGen.java:425)
	at javassist.compiler.CodeGen.atStmnt(CodeGen.java:363)
	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.CodeGen.atIfStmnt(CodeGen.java:398)
	at javassist.compiler.CodeGen.atStmnt(CodeGen.java:355)
	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:569)
	at javassist.CtBehavior.insertBefore(CtBehavior.java:754)
	... 50 more

@chibash
Copy link
Member

chibash commented Jan 24, 2019

The exception says the type of $r was not found.
I'm not sure what is the type of $r but you should check it is in the class path.

@tangzhenhuang
Copy link
Author

I think this is because "$r" doesn't have the effect of escaping, because even if I add Class.forName($type.getName()) before this, it doesn't help. According to the documentation, $r doesn't work. It should have the effect of escaping.

chibash added a commit that referenced this issue Jan 27, 2019
It makes $r available in the code given to CtBehavior#insertBefore().
@chibash
Copy link
Member

chibash commented Jan 27, 2019

OK, you're right. $r was not available in the code passed to insertBefore.
I've fixed this bug. Could you try javassist.jar available from HEAD of the master branch.

@tangzhenhuang
Copy link
Author

I have tried it, this bug no longer exists, thanks.

odl-github pushed a commit to opendaylight/odlparent that referenced this issue Oct 10, 2019
3.25 fixes:
- jboss-javassist/javassist#72
- jboss-javassist/javassist#241
- jboss-javassist/javassist#242
- jboss-javassist/javassist#246
- jboss-javassist/javassist#252
3.26 fixes:
- jboss-javassist/javassist#265
- jboss-javassist/javassist#270
- jboss-javassist/javassist#271
- jboss-javassist/javassist#275

Of these #270 is most important, as it fixes an issue we've seen
with powermock downstream.

Change-Id: Ib4d75d6411e71438436249a8eb9313ccf4411ca2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
odl-github pushed a commit to opendaylight/odlparent that referenced this issue Oct 17, 2019
3.25 fixes:
- jboss-javassist/javassist#72
- jboss-javassist/javassist#241
- jboss-javassist/javassist#242
- jboss-javassist/javassist#246
- jboss-javassist/javassist#252
3.26 fixes:
- jboss-javassist/javassist#265
- jboss-javassist/javassist#270
- jboss-javassist/javassist#271
- jboss-javassist/javassist#275

Of these #270 is most important, as it fixes an issue we've seen
with powermock downstream.

Change-Id: Ib4d75d6411e71438436249a8eb9313ccf4411ca2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 6a404f1)
odl-github pushed a commit to opendaylight/odlparent that referenced this issue Oct 17, 2019
3.25 fixes:
- jboss-javassist/javassist#72
- jboss-javassist/javassist#241
- jboss-javassist/javassist#242
- jboss-javassist/javassist#246
- jboss-javassist/javassist#252
3.26 fixes:
- jboss-javassist/javassist#265
- jboss-javassist/javassist#270
- jboss-javassist/javassist#271
- jboss-javassist/javassist#275

Of these #270 is most important, as it fixes an issue we've seen
with powermock downstream.

Change-Id: Ib4d75d6411e71438436249a8eb9313ccf4411ca2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 6a404f1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants