[jboss-jira] [JBoss JIRA] (JASSIST-195) Verifier error with try-finally clause in Java 1.7
John Brush (JIRA)
jira-events at lists.jboss.org
Sat Apr 27 03:50:53 EDT 2013
[ https://issues.jboss.org/browse/JASSIST-195?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
John Brush updated JASSIST-195:
-------------------------------
Description:
After upgrading from Java 1.6 to Java 1.7 our unit tests failed due to the new verifier in 1.7 which requires a stack map. I fixed this issue by adding a call to the rebuildStackMap() method after instrumentation, but this caused a new problem to pop up in one particular instance:
{code}
public int testInstrumentedCallInFinallyBlock( int i )
{
try
{}
catch ( Throwable t )
{}
finally
{
i = incByOne( i );
}
return i;
}
{code}
This unit test results in the following exception:
java.lang.VerifyError: Stack map does not match the one at exception handler 9 in method xxx.StatementsTestComponent.testInstrumentedCallInFinallyBlock(I)I at offset 9
After some investigation, I noticed that the problem occurred independent of my instrumentation, simply as a result of loading the byte code with Javassist, invoking rebuildStackMap() and then trying to load it. The byte code for the above snippet looks as follows before invoking rebuildStackMap():
{code}
Code:
stack=2, locals=3, args_size=2
0: aload_0
1: iload_1
2: invokespecial #3 // Method incByOne:(I)I
5: istore_1
6: goto 18
9: astore_2
10: aload_0
11: iload_1
12: invokespecial #3 // Method incByOne:(I)I
15: istore_1
16: aload_2
17: athrow
18: iload_1
19: ireturn
Exception table:
from to target type
9 10 9 any
StackMapTable: number_of_entries = 2
frame_type = 73 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 8 /* same */
{code}
Afterwards, it looks like this:
{code}
Code:
stack=2, locals=3, args_size=2
0: aload_0
1: iload_1
2: invokespecial #23 // Method incByOne:(I)I
5: istore_1
6: goto 18
9: nop
10: nop
11: nop
12: nop
13: nop
14: nop
15: goto 9
18: iload_1
19: ireturn
Exception table:
from to target type
9 10 9 any
StackMapTable: number_of_entries = 2
frame_type = 249 /* chop */
offset_delta = 9
frame_type = 253 /* append */
offset_delta = 8
locals = [ class ch/shaktipat/saraswati/instrument/busicomp/StatementsTestComponent, int ]
{code}
Notice the modifications from lines 9-15: this is a result of Javassist's MapMaker.fixDeadcode() method. I assume that the verify error is a result of the exception table entry that refers to code which is no longer there. A possible fix would be to make sure that any exception handlers referring to dead code are removed in such cases. Personally, I would prefer that Javassist simply not modify the code if at all possible, or at least for such modifications to be optional (configurable).
BTW: my only workaround for the time being is to force the 1.7 JVM to use the old verifier with -XX:-UseSplitVerifier.
was:
After upgrading from Java 1.6 to Java 1.7 our unit tests failed due to the new verifier in 1.7 which requires a stack map. I fixed this issue by adding a call to the rebuildStackMap() method after instrumentation, but this caused a new problem to pop up in one particular instance:
{code}
public int testInstrumentedCallInFinallyBlock( int i )
{
try
{}
catch ( Throwable t )
{}
finally
{
i = incByOne( i );
}
return i;
}
{code}
This unit test results in the following exception:
java.lang.VerifyError: Stack map does not match the one at exception handler 9 in method xxx.StatementsTestComponent.testInstrumentedCallInFinallyBlock(I)I at offset 9
After some investigation, I noticed that the problem occurred independent of my instrumentation, simply as a result of loading the byte code with Javassist, invoking rebuildStackMap() and then trying to load it. The byte code for the above snippet looks as follows before invoking rebuildStackMap():
{code}
Code:
stack=2, locals=3, args_size=2
0: aload_0
1: iload_1
2: invokespecial #3 // Method incByOne:(I)I
5: istore_1
6: goto 18
9: astore_2
10: aload_0
11: iload_1
12: invokespecial #3 // Method incByOne:(I)I
15: istore_1
16: aload_2
17: athrow
18: iload_1
19: ireturn
Exception table:
from to target type
9 10 9 any
StackMapTable: number_of_entries = 2
frame_type = 73 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 8 /* same */
{code}
Afterwards, it looks like this:
{code}
Code:
stack=2, locals=3, args_size=2
0: aload_0
1: iload_1
2: invokespecial #23 // Method incByOne:(I)I
5: istore_1
6: goto 18
9: nop
10: nop
11: nop
12: nop
13: nop
14: nop
15: goto 9
18: iload_1
19: ireturn
Exception table:
from to target type
9 10 9 any
StackMapTable: number_of_entries = 2
frame_type = 249 /* chop */
offset_delta = 9
frame_type = 253 /* append */
offset_delta = 8
locals = [ class ch/shaktipat/saraswati/instrument/busicomp/StatementsTestComponent, int ]
{code}
Notice the modifications from lines 9-15: this is a result of Javassist's MapMaker.fixDeadcode() method. I assume that the verify error is a result of the exception table entry that refers to code which is no longer there. A possible fix would be to make sure that any exception handlers referring to dead code are removed in such cases. Personally, I would prefer that Javassist simply not modify the code if at all possible, or at least for such modifications to be optional (configurable).
> Verifier error with try-finally clause in Java 1.7
> ---------------------------------------------------
>
> Key: JASSIST-195
> URL: https://issues.jboss.org/browse/JASSIST-195
> Project: Javassist
> Issue Type: Bug
> Affects Versions: 3.17.1-GA
> Environment: Oracle Java 1.7 on Mac OS X
> Reporter: John Brush
> Assignee: Shigeru Chiba
>
> After upgrading from Java 1.6 to Java 1.7 our unit tests failed due to the new verifier in 1.7 which requires a stack map. I fixed this issue by adding a call to the rebuildStackMap() method after instrumentation, but this caused a new problem to pop up in one particular instance:
> {code}
> public int testInstrumentedCallInFinallyBlock( int i )
> {
> try
> {}
> catch ( Throwable t )
> {}
> finally
> {
> i = incByOne( i );
> }
> return i;
> }
> {code}
> This unit test results in the following exception:
> java.lang.VerifyError: Stack map does not match the one at exception handler 9 in method xxx.StatementsTestComponent.testInstrumentedCallInFinallyBlock(I)I at offset 9
> After some investigation, I noticed that the problem occurred independent of my instrumentation, simply as a result of loading the byte code with Javassist, invoking rebuildStackMap() and then trying to load it. The byte code for the above snippet looks as follows before invoking rebuildStackMap():
> {code}
> Code:
> stack=2, locals=3, args_size=2
> 0: aload_0
> 1: iload_1
> 2: invokespecial #3 // Method incByOne:(I)I
> 5: istore_1
> 6: goto 18
> 9: astore_2
> 10: aload_0
> 11: iload_1
> 12: invokespecial #3 // Method incByOne:(I)I
> 15: istore_1
> 16: aload_2
> 17: athrow
> 18: iload_1
> 19: ireturn
> Exception table:
> from to target type
> 9 10 9 any
> StackMapTable: number_of_entries = 2
> frame_type = 73 /* same_locals_1_stack_item */
> stack = [ class java/lang/Throwable ]
> frame_type = 8 /* same */
> {code}
> Afterwards, it looks like this:
> {code}
> Code:
> stack=2, locals=3, args_size=2
> 0: aload_0
> 1: iload_1
> 2: invokespecial #23 // Method incByOne:(I)I
> 5: istore_1
> 6: goto 18
> 9: nop
> 10: nop
> 11: nop
> 12: nop
> 13: nop
> 14: nop
> 15: goto 9
> 18: iload_1
> 19: ireturn
> Exception table:
> from to target type
> 9 10 9 any
> StackMapTable: number_of_entries = 2
> frame_type = 249 /* chop */
> offset_delta = 9
> frame_type = 253 /* append */
> offset_delta = 8
> locals = [ class ch/shaktipat/saraswati/instrument/busicomp/StatementsTestComponent, int ]
> {code}
> Notice the modifications from lines 9-15: this is a result of Javassist's MapMaker.fixDeadcode() method. I assume that the verify error is a result of the exception table entry that refers to code which is no longer there. A possible fix would be to make sure that any exception handlers referring to dead code are removed in such cases. Personally, I would prefer that Javassist simply not modify the code if at all possible, or at least for such modifications to be optional (configurable).
> BTW: my only workaround for the time being is to force the 1.7 JVM to use the old verifier with -XX:-UseSplitVerifier.
--
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
More information about the jboss-jira
mailing list