[jboss-jira] [JBoss JIRA] (JASSIST-222) Using insertBeforeBody to insert try/catch block in constructor can generate invalid bytecode for certain Java compilers
Manuel Geffken (JIRA)
issues at jboss.org
Mon May 5 08:56:56 EDT 2014
Manuel Geffken created JASSIST-222:
--------------------------------------
Summary: Using insertBeforeBody to insert try/catch block in constructor can generate invalid bytecode for certain Java compilers
Key: JASSIST-222
URL: https://issues.jboss.org/browse/JASSIST-222
Project: Javassist
Issue Type: Bug
Affects Versions: 3.18.0-GA
Environment: Unknown java compiler generating class files with major version 45, minor version 3.
Mint Linux, JDK 1.7.
Reporter: Manuel Geffken
Assignee: Shigeru Chiba
Priority: Minor
The class S in the "boyer" benchmark of the Ashes Suite Collection (http://www.sable.mcgill.ca/ashes/) (no original source code available) has the following bytecode according to javap:
Classfile ashesSuiteCollection/suites/ashesHardTestSuite/benchmarks/boyer/classes/S.class
Last modified May 2, 2014; size 154 bytes
MD5 checksum e79a1481a39d40004bc504cc4f7c2641
class S
minor version: 3
major version: 45
flags: ACC_SUPER
Constant pool:
...
{
protected int $;
flags: ACC_PROTECTED
protected S(int);
flags: ACC_PROTECTED
Code:
stack=3, locals=2, args_size=2
0: aload_0
1: iload_1
2: aload_0
3: invokespecial #14 // Method java/lang/Object."<init>":()V
6: putfield #13 // Field $:I
9: return
}
An instrumentation of this class' constructor with a try/catch block as in
CtConstructor[] ctors = target.getDeclaredConstructors();
for (CtConstructor ctor : ctors) {
StringBuilder headerSB = new StringBuilder();
headerSB.append("{");
headerSB.append(" try {");
headerSB.append(" throw new java.lang.Exception();");
headerSB.append(" } catch(java.lang.Exception e) {}");
headerSB.append("}");
ctor.insertBeforeBody(headerSB.toString());
}
causes an invalid class file that does not verify:
Classfile /home/geffken/git/X2Traverse/benchmarks/basic/ashesSuiteCollection/suites/ashesHardTestSuite/benchmarks/boyer/out_classes/S.class
Last modified May 5, 2014; size 356 bytes
MD5 checksum d4ef556ee82cee6c4c2960b43d7e71e1
class S
minor version: 3
major version: 45
flags: ACC_SUPER
Constant pool:
...
{
protected int $;
flags: ACC_PROTECTED
protected S(int);
flags: ACC_PROTECTED
Code:
stack=5, locals=3, args_size=2
0: aload_0
1: iload_1
2: aload_0
3: invokespecial #14 // Method java/lang/Object."<init>":()V
6: new #22 // class java/lang/Exception
9: dup
10: invokespecial #23 // Method java/lang/Exception."<init>":()V
13: athrow
14: astore_2
15: goto 18
18: putfield #13 // Field $:I
21: return
Exception table:
from to target type
6 14 14 Class java/lang/Exception
}
The problem is that the operand stack can be empty when the putfield instruction is reached. The problem seems might be rooted in the following bytecode sequence.
1: iload_1
2: aload_0
3: invokespecial #14 // Method java/lang/Object."<init>":()V
In contrast the reconstructed source code (the source is not available)
public class S {
int $;
public S(int i) {
$ = i;
}
}
compiled with javac 1.7.0_51 (javac -source 1.3 -target 1.1) produces
Classfile S.class
Last modified May 5, 2014; size 222 bytes
MD5 checksum 9700e6458db9d62e640018421a079761
Compiled from "S.java"
public class S
SourceFile: "S.java"
minor version: 3
major version: 45
flags: ACC_SUPER
Constant pool:
...
{
int $;
flags:
public S(int);
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iload_1
6: putfield #2 // Field $:I
9: return
}
This version can be instrumented as shown above without problems. Here the respective bytecode sequence is as follows which seems easier to instrument with code containing a try/catch block after the super call.
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iload_1
--
This message was sent by Atlassian JIRA
(v6.2.3#6260)
More information about the jboss-jira
mailing list