[
https://issues.jboss.org/browse/JASSIST-241?page=com.atlassian.jira.plugi...
]
Patson Luk commented on JASSIST-241:
------------------------------------
Dig a bit deeper into the code, it appears that below is the cause of the exception :
(excuse me if any of below reasoning is incorrect as I am not too familiar with the
libray)
# "insertAfter" on method replaces return statement with "goto" that
jumps to the injected code
# In order to replace the RETURN op with GOTO, it needs to allocate a bigger block as GOTO
take more byte, it attempts to insert gap of size 2 (not a wide goto)
(CtBehavior.insertGoto)
# During the gap insertion, CodeIterator checks the byte alignment of the method, if
there's TABLESWITCH (my case) or LOOKUPSWITCH, it will throws AlignmentException as
the require the gapLength to be multiple of 4
# To insert a gap of multiple of 4, The end result will be a GOTO followed with 2 NOOP
# Now in the class MapMaker, it attempts to build the stackmap
# It builds a list of BasicBlock, the sequence would be (at the entrance of
MapMaker.toStackMap)
#* The IfNotNull (branch instruction block)
#* The GOTO block (if o is null, used to be a return but now replaced by GOTO because of
code injection)
#* The 2 NOOPS block (dead code - inserted by the GAP ) with incoming=1 (after the
fixDeadcode)
#* The target "branch-to" block of ifNotNull with incoming = 1 (as IfNotNull
jumps to this)
# Now in MapMaker.isTarget logic, it checks whether the block is a "branch
target". To my understanding if incoming > 1, that means it should be a branch
target (makes sense), if it's zero then it should NOT be a branch trarget (also makes
sense), if it's 1, then it checks if the previous block has stop == true (ends with an
unconditional jump), this logic makes sense MOST of the case as if the previous block is
unconditional jump and this block still has incoming == 1, that means someone else
branches to this block (*Just my assumption/understanding, could be wrong!*) This however,
creates problem if a branch target is preceded by a piece of dead code which has stop ==
false
So my thought is that can we flag if a block is a dead code? It seems like javassist
already has the logic to find out dead code block (fixDeadCode) and BasicBlock.makeBlocks.
And in the logic of MapMaker.isTarget, if the previous block is dead code and if the
"incoming" of current block == 1, that means this current block is a valid
branch target as dead code does not increment the following block.
Hopefully i capture the problem correctly, apologize if i have made any false
assumptions!
VerifyError: Expecting a stackmap frame - Switch case statement Java
7
----------------------------------------------------------------------
Key: JASSIST-241
URL:
https://issues.jboss.org/browse/JASSIST-241
Project: Javassist
Issue Type: Bug
Affects Versions: 3.19.0-GA
Environment: jdk7
Reporter: Patson Luk
Assignee: Shigeru Chiba
This could be a duplicate of issue 215 and 205.
Tested it on the master (3.19.0-GA) with java 7. Running the below class
{code}
import java.util.Random;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
public class TestDriver {
public static void main(String[] args) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("TestClass");
CtMethod testMethod = cc.getMethod("test",
"(Ljava/lang/Object;)V");
testMethod.insertAfter("System.out.println(\"inserted!\");");
cc.toClass();
//invoke it
TestClass.test(new Object());
}
}
class TestClass {
public static void test(Object o) {
//part 1
if (o == null) {
return;
}
//part 2
int oper = new Random().nextInt();
switch (oper) {
case 1:
break;
}
}
}
{code}
Triggers error message as below:
{quote}
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at
branch target 9 in method TestClass.test(Ljava/lang/Object;)V at offset 1
at TestDriver.main(TestDriver.java:19)
{quote}
*Please take note that:*
# This is observed on Java 7. When the same code is run on Java 6, it is fine
# Both the "part 1" - return statement (commented in the code above) and
"part 2" - switch/case statement have to be there to trigger the error. If
either of those are commented out, then the code runs fine
--
This message was sent by Atlassian JIRA
(v6.3.11#6341)