[
http://jira.jboss.com/jira/browse/JASSIST-52?page=comments#action_12408228 ]
Yanic Inghelbrecht commented on JASSIST-52:
-------------------------------------------
Thank you very much for the explanation, it has allowed me to fix the issue on my end!
Contrary to the example I posted, I actually wanted to catch the exception, process it and
then throw it again.
So the limitation you explained should not apply to what I am trying to do, but I did run
into because of the way I coded the replacement block.
Here's why :
The replacement block looked somewhat like the following
{
// .. here do something "beforeProceed"
Throwable caught=null;
try {
$_=$proceed($$);
} catch (Throwable t) {
caught=t;
}
if (caught==null) {
// .. here do something "afterProceedNoException"
} else {
// .. here do something "afterProceedException"
throw caught;
}
}
With the information you provided, I realized I can use the following (simpler!) code to
achieve the same :
{
// .. here do something "beforeProceed"
try {
$_=$proceed($$);
// .. here do something "afterProceedNoException"
} catch (Throwable t) {
// .. here do something "afterProceedException"
throw t;
}
}
Don't ask why I didn't come up with the simpler second fragment in the first
place, it must've been one of those days ;o)
Perhaps the documentation of ExprEditor#edit(MethodCall m) can be expanded to mention that
one cannot 'swallow' an exception when replacing a method call, with a link to
this JIRA entry for those who want more information?
Oh, I sent you an email @is.titech.ac.jp on March 20th, about how I would like to thank
you for your efforts in creating and maintaining javassist. Let me know if you're
(not) interested..
Best regards,
Yanic
VerifyError (inconsistent stack height) through MethodCall#replace
when block includes a try/catch block
--------------------------------------------------------------------------------------------------------
Key: JASSIST-52
URL:
http://jira.jboss.com/jira/browse/JASSIST-52
Project: Javassist
Issue Type: Bug
Environment: javassist 3.7.1 (from cvs HEAD), jdk 1.6.0_03 on winXP
Reporter: Yanic Inghelbrecht
Assigned To: Shigeru Chiba
Attachments: supplement_to_jassist-52.zip
Included is the simplest test case I could find that reproduces the error, it consists of
two classes : Client (to be instrumented) and Main (does the instrumentation).
When run, it produces the following exception trace :
Exception in thread "main" java.lang.VerifyError: (class:
test_verify_error_with_try_catch_in_replace/Client, method: instrumentMe signature: ()V)
Inconsistent stack height 0 != 2
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
at java.lang.Class.getConstructor0(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at test_verify_error_with_try_catch_in_replace.Main.main(Main.java:30)
The error disappears in all of the following cases (so it must be related to them I
guess) :
- when the try/catch block is removed from the replacement block
- when the string concatenation happens without using two local variables
- when the string concatenation is removed but the local variables are kept
This is related (for me at least) to JIRA JAVASSIST 51, where a similar error occurred
for NewExpr (and was quickly fixed, thanks again for that!!).
Just like issue 51, it is a show stopper for our project since it all ties in with the
support for exceptions in the development tool we're creating, so I hope you will
again regard it as an urgent issue.
Thanks in advance.
Best regards,
Yanic
-- source code for client.java
package test_verify_error_with_try_catch_in_replace;
public class Client {
public void instrumentMe() throws Exception {
// the error is somehow related to the string concatenation and local variables,
// when the code below is replaced with something else, the error does not occur.
String s1 = "a";
String s2 = s1 + "b";
}
}
-- source code for Main.java
package test_verify_error_with_try_catch_in_replace;
import java.lang.reflect.Method;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Loader;
import javassist.NotFoundException;
import javassist.Translator;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
public class Main {
public static void main(String[] args) throws Exception {
ClassPool pool = new ClassPool(true);
Loader cl = new Loader();
try {
cl.addTranslator(pool, new MyTranslator());
} catch (Exception e) {
e.printStackTrace();
return;
}
// load the Client class
Class
clientClass=cl.loadClass("test_verify_error_with_try_catch_in_replace.Client");
// create an instance
Object client=clientClass.newInstance();
// execute Client#instrumentMe
Method callMethod=clientClass.getMethod("instrumentMe", new Class[]{});
callMethod.invoke(client, new Object[]{});
}
static public class MyTranslator extends ExprEditor implements Translator {
public void onLoad(ClassPool pool, String classname) throws NotFoundException,
CannotCompileException {
CtClass cc = pool.get(classname);
modify(cc);
}
public void modify(CtClass c) throws CannotCompileException {
for (CtMethod m : c.getMethods()) {
m.instrument(this);
}
}
@Override
public void edit(MethodCall mc) throws CannotCompileException {
// simple proceed surrounded by a try/catch block
String block = "{try{$_=$proceed($$);} catch(Throwable t) {}}";
mc.replace(block);
}
public void start(ClassPool pool) throws NotFoundException, CannotCompileException {
// do nothing
}
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira