-
Notifications
You must be signed in to change notification settings - Fork 586
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
javaagent/java 7 and custom javassist not working together: stack shape inconsistent #549
Comments
From gdel...@gmail.com on December 02, 2014 09:28:36 I forgot to say that, to isolate the problem, I made a really dummy class being this: public class TestA {
} And under Java 7, it runs fine without the powermock agent, as soon as I add the VM argument: -javaagent:powermock-module-javaagent-1.6.0.jar |
From gdel...@gmail.com on December 18, 2014 04:34:55 Output with a JRE 7 SUN 32 bits is the following:
|
From gdel...@gmail.com on December 19, 2014 02:32:51 The problem seems to come from the transformer class org.powermock.modules.agent.DefinalizingClassTransformer which rewrites the bytecode of class when loading. I guess there is something wrong in the rewriting from the ClassWriter or PowerMockClassVisitor classes but for now I don't have enough knowledge nor time to tell where is the problem. |
From gdel...@gmail.com on December 19, 2014 02:36:11 Also for the moment I found a workaround/fix (don't know if there is a way to fix the agent to make it work without the flag). I explain here ( http://www.notonlyanecmplace.com/java-7-enforces-bytecode-verification/ ) but basically you can just disable the bytecode verification on IBM JRE or fallback to the old one on SUN JRE. I'll try to see if there is a better fix so it passes the verification, but help from the author would be nice because it is a bit too much for me now :) |
When using the powermock-module-junit4-rule-agent there are java.lang.VerifyErrors. For example if you have some project with Spock 1.0 and use use the rule, it works just fine. As soon as you upgrade to 1.2 or 1.3 which dropped Java 6 support, you get various of these verify errors. They are all about "Expected stackmap frame at this location.". I'm no Byte Buddy expert, but from what I have read, the combination of ClassWriter.COMPUTE_MAXS with ClassReader.SKIP_FRAMES is not the best idea. ClassReader.SKIP_FRAMES will skip reading and visiting stack maps and stack map tables. The JavaDoc of that attribute says it is for example useful if you use ClassWriter.COMPUTE_FRAMES as it recalculates the stackmap frames anyway, so there is no need to parse and visit them. But like it is currently, they are neither parsed, nor visited, nor computed and thus they are missing when verifying. As far as I understood there are two ways to handle this, either use ClassWriter.COMPUTE_FRAMES and ClassReader.SKIP_FRAMES, as then the frames are not parsed or visited, but recalculated, or do not use both as they are then parsed, visited and in the case of this visitor just copied. As the visitor only removes the final modifiers for methods and classes now, I renamed it, disabled even the MAXS computation and disabled the frame skipping. From my test it seems to work better with this setting now and also all your tests are green (except three tests that are red for me even without my changes). Fixes #1005 Probably fixes #956, #1024, #926, #549, #558, #873, #693, #543 Update: also re-enabled the tests that were disabled due to this error in #952 I think the exclusion of TestNG classes in commit e948b49 was also due to this error and could probably be reverted. Work-around: Use JVM option -noverify to disable the verification that complains about the missing stackmap frames.
Probably fixed by #1043 |
From gdel...@gmail.com on December 02, 2014 18:23:18
What steps will reproduce the problem? 1. Write an empty test with a before class method
2. add as content of the beforeClass method this:
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("java.lang.String");
ClassFile cf = cc.getClassFile();
List methods = cf.getMethods();
for (MethodInfo m : methods) {
System.out.println(m.getName());
}
3. Add the javaagent to the VM argument : -javaagent:powermock-module-javaagent-1.6.0.jar, in the run classpath, set the javaagent jar first
4. Make sure to set the compliance of the project to 1.7 (using a JRE 7)
4. Launch test with the standard JUnit4 runner What is the expected output? What do you see instead? I expect the test to pass as with Java 6, instead I get:
java.lang.VerifyError: JVMVRFY012 stack shape inconsistent; class=TestPSC, method=beforeClass()V, pc=29
at java.lang.J9VMInternals.prepareClassImpl(Native Method)
at java.lang.J9VMInternals.prepare(J9VMInternals.java:430)
at java.lang.Class.getMethod(Class.java:1061)
at org.junit.internal.builders.SuiteMethodBuilder.hasSuiteMethod(SuiteMethodBuilder.java:18)
at org.junit.internal.builders.SuiteMethodBuilder.runnerForClass(SuiteMethodBuilder.java:10)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.(JUnit4TestReference.java:33)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.(JUnit4TestClassReference.java:25)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) What version of the product are you using? On what operating system? JUnit 4.11, Powermock 1.6.0, javassist 3.18.2-GA Please provide any additional information below. Launching with a compliance 1.6 works perfectly fine, launching with 1.7 fails. I have also tried to add the option -XX:-UseSplitVerifier. And the javaagent jar is first in the classpath.
Any ideas?
Thank you!
Guillaume
The class is:
Original issue: http://code.google.com/p/powermock/issues/detail?id=529
The text was updated successfully, but these errors were encountered: