lishunli / powermock

Automatically exported from code.google.com/p/powermock
Apache License 2.0
0 stars 0 forks source link

Powermock / Javassist creates illegal constructors for JDK 1.7.0u65 and 1.8.0u11 with -target 7 #505

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I have simple class with a super class that needs to get power-mocked, but 
Powermock / Javassist creates illegal constructors for JDK 1.7.0u65 and 
1.8.0u11 with -target 7.

Somewhere in MainMockTransformer.transform(clazz), I think inside the 
PowerMockExpressionEditor something happens 

If you remove -target 7 it works for both JDK 1.7.0u65 and 1.8.0u11.

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.003 sec <<< 
FAILURE! - in ConstructorTest
testConstructorManipulationFailure(ConstructorTest)  Time elapsed: 0.002 sec  
<<< ERROR!
java.lang.VerifyError: Bad <init> method call from inside of a branch
Exception Details:
  Location:
    MockedClass.<init>()V @32: invokespecial
  Reason:
    Error exists in the bytecode
  Bytecode:
    0000000: 2a4c 120f b800 1503 bd00 0d12 16b8 001a
    0000010: b800 204e 2db2 0024 a500 0e2a 01c0 0026
    0000020: b700 29a7 0009 2bb7 002b 0157 b1       
  Stackmap Table:
    full_frame(@38,{UninitializedThis,UninitializedThis,Top,Object[#13]},{})
    full_frame(@44,{Object[#2],Object[#2],Top,Object[#13]},{})

    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2658)
    at java.lang.Class.getDeclaredConstructors(Class.java:2007)
    at ConstructorTest.testConstructorManipulationFailure(ConstructorTest.java:13)

See attachment or https://github.com/burka/powermock-javassist-bug for a full 
(not) working example.

Original issue reported on code.google.com by f...@noidea.de on 18 Jul 2014 at 11:04

Attachments:

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
It seems to boil down to the branching before the super() call for the 
constructor created inside the ExprEditor in powermocks MainMockTransformer 
Line 269-273

code.append("if(value == 
").append(MockGateway.class.getName()).append(".PROCEED) {");
code.append("   $_ = $proceed($$);");
code.append("} else {");
code.append("   $_ = 
").append(getCorrectReturnValueType(returnTypeAsCtClass)).append(";");
code.append("}}");

I could reproduce it with pure javassist with a javassist.expr.ExprEditor 
instrumented class with

@Override
public void edit(ConstructorCall c) throws CannotCompileException
{
    ClassPool classPool = this.clazz.getClassPool();
    CtClass constructorType = classPool.get(ConstructorClass.class.getName());
    this.clazz.addConstructor(CtNewConstructor.make(new CtClass[] { constructorType}, new CtClass[0], "{super();}", this.clazz));
    c.replace("if (1 != 2){ super();}");
}

Updated code at github.

So javassist produces illegal bytecode due to powermock asking to branch in a 
constructor before a super constructor call.
So Powemock must avoid this 'if' in the PowerMockExpressionEditor during that 
constructor call. 

I opened a Issue at javassist, too: https://issues.jboss.org/browse/JASSIST-228

Original comment by f...@noidea.de on 18 Jul 2014 at 1:03

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
A MemberMatcher.suppress(MemberMatcher.constructor(MockedClass.class));
before any powermocked mock initialization does not work as a workaround, as 
the code of the constructor was already modified.
See updated project on github.

Original comment by f...@noidea.de on 18 Jul 2014 at 1:28

GoogleCodeExporter commented 9 years ago
Updated code to reproduce the issue.

Original comment by f...@noidea.de on 18 Jul 2014 at 1:48

Attachments:

GoogleCodeExporter commented 9 years ago
This might be a JDK bug, see https://bugs.openjdk.java.net/browse/JDK-8051012 . 

Original comment by lari.hot...@sagire.fi on 21 Jul 2014 at 4:05

GoogleCodeExporter commented 9 years ago

Original comment by johan.ha...@gmail.com on 25 Aug 2014 at 6:01

GoogleCodeExporter commented 9 years ago
I realize this is 8+ months too late but in case someone else comes looking 
here upgrading from java 7u71 to 7u75 fixed the problem for me. 

Original comment by hard...@gmail.com on 27 Feb 2015 at 7:51