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

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

Closed
johanhaleby opened this Issue Jul 25, 2015 · 7 comments

Comments

Projects
None yet
2 participants
@johanhaleby
Collaborator

johanhaleby commented Jul 25, 2015

From f...@noidea.de on July 18, 2014 13:04:39

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 method call from inside of a branch
Exception Details:
Location:
MockedClass.()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.

Attachment: powermock-javassist-bug.tar.gz

Original issue: http://code.google.com/p/powermock/issues/detail?id=505

@johanhaleby

This comment has been minimized.

Show comment
Hide comment
@johanhaleby

johanhaleby Jul 25, 2015

Collaborator

From f...@noidea.de on July 18, 2014 06:03:52

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

Collaborator

johanhaleby commented Jul 25, 2015

From f...@noidea.de on July 18, 2014 06:03:52

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

@johanhaleby

This comment has been minimized.

Show comment
Hide comment
@johanhaleby

johanhaleby Jul 25, 2015

Collaborator

From f...@noidea.de on July 18, 2014 06:28:36

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.

Collaborator

johanhaleby commented Jul 25, 2015

From f...@noidea.de on July 18, 2014 06:28:36

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.

@johanhaleby

This comment has been minimized.

Show comment
Hide comment
@johanhaleby

johanhaleby Jul 25, 2015

Collaborator

From f...@noidea.de on July 18, 2014 06:48:55

Updated code to reproduce the issue.

Attachment: powermock-javassist-bug.tar.bz2

Collaborator

johanhaleby commented Jul 25, 2015

From f...@noidea.de on July 18, 2014 06:48:55

Updated code to reproduce the issue.

Attachment: powermock-javassist-bug.tar.bz2

@johanhaleby

This comment has been minimized.

Show comment
Hide comment
@johanhaleby

johanhaleby Jul 25, 2015

Collaborator

From lari.hot...@sagire.fi on July 21, 2014 09:05:04

This might be a JDK bug, see https://bugs.openjdk.java.net/browse/JDK-8051012 .

Collaborator

johanhaleby commented Jul 25, 2015

From lari.hot...@sagire.fi on July 21, 2014 09:05:04

This might be a JDK bug, see https://bugs.openjdk.java.net/browse/JDK-8051012 .

@johanhaleby

This comment has been minimized.

Show comment
Hide comment
@johanhaleby

johanhaleby Jul 25, 2015

Collaborator

From johan.ha...@gmail.com on August 24, 2014 23:01:21

Status: Duplicate
Mergedinto: 504

Collaborator

johanhaleby commented Jul 25, 2015

From johan.ha...@gmail.com on August 24, 2014 23:01:21

Status: Duplicate
Mergedinto: 504

@johanhaleby

This comment has been minimized.

Show comment
Hide comment
@johanhaleby

johanhaleby Jul 25, 2015

Collaborator

From hard...@gmail.com on February 27, 2015 11:51:24

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.

Collaborator

johanhaleby commented Jul 25, 2015

From hard...@gmail.com on February 27, 2015 11:51:24

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.

@achikin

This comment has been minimized.

Show comment
Hide comment
@achikin

achikin Apr 6, 2016

Replicates on MacOSX:

> java -version
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)

achikin commented Apr 6, 2016

Replicates on MacOSX:

> java -version
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment