[
https://issues.jboss.org/browse/JASSIST-204?page=com.atlassian.jira.plugi...
]
Dordoriko Beanie commented on JASSIST-204:
------------------------------------------
Hello Chiba-san,
Thank you for responding.
I am not sure if I understand you correctly; The stack is indeed not empty before
invoking the RETURN instruction, and indeed in this case the .class file wasn't
produced "natively" from a java source by the javac compiler.
However, this isn't 'broken' according to the JVM specification, because the
documentation of the RETURN-type instructions specifically discusses the situation that
the stack depth (beyond the base of the current frame) isn't zero - it says that these
extra entries [beyond the return value, if applicable] are popped / discarded
automatically.
You can find this sentence in the spec for areturn/freturn/...: "All other items on
the current method's operand stack are discarded."
And this sentence for 'return' (no args): "All items on the current
method's operand stack are discarded."
Also, several different JVM's are able to correctly run a .class file which has this
behavior, which further stresses that this is acceptable by the JVM.
Please let me know if this clarifies the situation, or elaborate to me what you meant by
broken.
Again thank you very much,
Dori
Getting java.lang.VerifyError when adding try/catch to a method using
CtMethod.insertAfter, if the method returns when the JVM stack is not empty - Inconsistent
stack height 0 != 1, or Inconsistent stackmap frames at branch target
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key: JASSIST-204
URL:
https://issues.jboss.org/browse/JASSIST-204
Project: Javassist
Issue Type: Bug
Affects Versions: 3.17.0-GA, 3.18.0-GA
Environment: Occurred on Windows with standard HotSpot JVM (1.6.0_24, 1.7.0_21,
..), also with IBM J9 JVM on AIX etc.
Reporter: Dordoriko Beanie
Assignee: Shigeru Chiba
Labels: VerifyError, height, insertBefore, stack
Attachments: popnopbug.zip
After instrumenting certain classes with insertAfter(), I am consistently getting
java.lang.VerifyError when trying to load the instrumented class(either "Inconsistent
stack height 0 != 1" or "Inconsistent stackmap frames at branch target",
depending on whether I'm on a newer 1.7 environment or an older one). The class was
perfectly loadable prior to instrumentation, even though it exhibits a slightly unusual
property that its return-type instructions are not necessarily executed when the stack is
empty (not counting the return parameter, if applicable).
The problem originally occurred with some class file that was apparently weaved by
AspectJ 1.5.2a, but it was then reproduced by combining the following circumstances:
1) That the instrumented method has the "odd" property that it has an
areturn/ireturn/return instruction which is invoked when the stack is not empty (when
there are one or more values that were pushed onto the current frame and weren't
popped). Note that I was unable to produce this with a freshly compiled .java source, so
instead I took a simple .class file and changed one of the popping instructions to a nop
instruction using a hex editor.
2) That the code added by insertAfter() contains a try/catch structure or something
similar (which forces the stack height to be reset in case of catch). It is possible that
this wasn't really necessary and that similar symptoms could occur by just having
multiple return statements with different stack heights.
When this happens, javassist replaces the original return-type instruction with a goto
(when the stack height is N), but also adds a goto to the same label from the end of the
catch clause (when the stack height is 0).
runtest_modified_nop_java17.bat
Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames
at branch target 35 in method com.test.HelloWorld.g()Ljava/lang/String; at offset 20
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.getMainMethod(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
runtest_modified_nop_java12.bat
Exception in thread "main" java.lang.VerifyError: (class: com/test/HelloWorld,
method: g signature: ()Ljava/lang/String;) Inconsistent stack height 0 != 1
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.getMainMethod(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see:
http://www.atlassian.com/software/jira