[
https://issues.jboss.org/browse/JASSIST-210?page=com.atlassian.jira.plugi...
]
Patson Luk edited comment on JASSIST-210 at 4/28/14 1:04 PM:
-------------------------------------------------------------
Many thanks for the detailed reply!
Since the JVM pops everything off the operation stack, looks like either we would have to
track whatever is the operand stack (such that we can restore at the end of the catch
block before the goto instruction) which is extremely complicated (don't know if
it's even feasible)
or
refactor the code and take the target method invocation out if it's a part of another
method's invocation, such that
ref.testMethod1(ref.testMethod2()); becomes
Ref tempVar = ref.testMethod2();
ref.testMethod(tempVar)
then I can add the try catch statement before or after the testMethod2 invocation
statement (but not wrapping it).
I will try the latter. Thanks!
was (Author: pluk):
Many thanks for the detailed reply!
There is still one piece that I do not quite understand, would you please kindly
elaborate?
You mentioned that after the translation 2 and 3 are replaced with a try-catch statement,
but in the sample code, the replacement block $_ = $proceed($$) itself is NOT surrounded
by try-catch, only the injected System.out... was surrounded by try-catch:
"{ try
{ System.out.println(\"injected\"); }
catch (Exception e)
{ e.printStackTrace(); }
$_ = $proceed($$); }";
Therefore, if $_ = $proceed($$) does throw exception, it should still follow the same flow
as if there is no try-catch? (as that piece of the code is not really wrapped)
Many thanks for your clarification in advanced
MethodCall.replace() throws inconsistent stack height in certain
scenarios
--------------------------------------------------------------------------
Key: JASSIST-210
URL:
https://issues.jboss.org/browse/JASSIST-210
Project: Javassist
Issue Type: Bug
Affects Versions: 3.16.1-GA, 3.18.1-GA
Reporter: Patson Luk
Assignee: Shigeru Chiba
Tested on 3.16.1-GA
This is similar to
https://issues.jboss.org/browse/JASSIST-52, but the try-catch block
usage is different (not wrapping the $proceed($$))
Based on the javassist tutorial, the substituted code for MethodCall.replace():
{{Note that the substituted code is not an expression but a statement or a block. It
cannot be or contain a try-catch statement.}}
However in the case that try-catch does not wrap the $_=$proceed($$);
It seems to work properly. For example:
ctClass.instrument(new ExprEditor() {
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("testMethod2")) {
String newBlock = "{ try { System.out.println(\"injected\"); }
catch (Exception e) { e.printStackTrace(); } $_ = $proceed($$); }";
m.replace(newBlock);
}
}
});
{{which ctClass is class TestReplace, which has code as below:}}
public class TestReplace {
public static void main(String[] args) {
RefClass ref = new RefClass();
ref.testMethod2();
}
}
class RefClass {
public void testMethod1(Object o) {}
public Object testMethod2() { return null; }
}
{{running TestReplace with the modified bytecode correctly prints "injected" to
the screen. However if I add one more line to the TestReplace's main() method}}
ref.testMethod1(ref.testMethod2());
{{It throws exception as below}}
javassist.bytecode.BadBytecode: inconsistent stack height -1
javassist.bytecode.stackmap.Tracer.doOpcode(Tracer.java:106)
*So is try-catch acceptable if it does not wrap the $_=$proceed($$)? If so, is it a bug
if it does not work properly for method invocation within another method invocation?*
Many thanks in advance!
--
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