Hi Amol!

First of all, I would suggest to read through the section of the JVM specification that describes how a try-finally block is to be compiled into bytecode by use of the jsr and ret instructions (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Compiling.doc.html#13789).

As you correctly stated there are two ways to exit a method on the bytcode level: by explicitly returning
or by throwing an exception. In BCEL you can cope with the second one easily by adding a new exception handler that encloses the critical code section. You can do so by calling MethodGen.addExceptionHandler(...). The last parameter to this method takes the type of exception
to be caught by this handler. To accept any type, simply use null. At the target of the exception handler you
have to jump to your finally block.

Secondly you have to insert code before each return instruction in the method code, which is slightly more complicated. I did so by utilizing the Visitor facility of BCEL. A convenient way is to sublcass org.apache.bcel.generic.EmptyVisitor and overwrite all visit* methods that handle return instructions, e.g. visitRETURN, visitARETURN, etc.

For example in my code the visitDRETURN (for double values) looks like the following:

//double has a word size of 2
public void visitDRETURN(DRETURN obj) {
if (max - offset < 2) max += (2 - max + offset);

//store away return value on the stack
code.insert(handle, new DSTORE(offset + 1));
code.insert(handle, new JSR(finallyClause));
code.insert(handle, new DLOAD(offset + 1));
}

Since you need to store away the return value that is on the top of the stack before the respective return instruction is called, you need some extra local variables. In the case of a double value you will need 2 slots. The first line of the method is dedicated to reserving enough slots (Don't mind the details). Then the value on top of the stack is stored away with DSTORE, the finally block is called with JSR (finallyClasue contains the instruction handle to the first instruction of the finally clause) and in the end the previously stored value will be pushed back on the stack again. The handle variable in the code above holds an instruction handle to the actual return instruction. I initialize it in a visitInstructionList() method in the visitor, which iterates over all instructions within a given interval of instruction handles of an InstructionList, and which I call initially to modify all return instructions.

So to sum up here is what I do in my instrumentation code:

*) Retrieve MethodGen of the method to be instrumented
*) Append instructions of finally block. See the link to the JVM specification above how to code a finally clause. Store away the instruction handle to the first instruction of the block.
*) Insert instructions for exception handler before the finally block. There you have to ASTORE the exception on the top of the stack, call JSR to jump to the first instruction of the finally block, ALOAD the exception back on the stack and ATHROW it.
*) Run the whole original code through an instance of the return instruction visitor. You will need to pass the instruction handle to the finally block to the visitor by some way.
*) Make sure that maxLocals and maxStack properties of the MethodGen get the correct values assigned.

Cheers,
Volker.

P.S. I would suggest to transfer the thread to the bcel users list, so that others could possibly profit from it, or perhaps someone points me to a mistake in my solution I'm not aware of yet. If you have any questions, it would be best to post it there.


Amol Kulkarni wrote:

Hi Volker,

I'm working on bytecode instrumentation of java
classes. I'm facing a problem tracing the method exit
points. As you must be fully aware that method can
exit from nay point due to exception and/or multiple
return statements. So I plan to encapsulate the whole
method body in to try-finally block and add my code
snippet in the finally block. I understand that its
very very complicated and found that you have already
worked out on this from the link
http://www.mail-archive.com/bcel-user@;jakarta.apache.org/msg00132.html.

Can you help me in this problem by providing the
details of "How to add try-finally block to a
method?".

Thanx.

Regards,
Amol

__________________________________________________
Do you Yahoo!?
Y! Web Hosting - Let the expert host your web site
http://webhosting.yahoo.com/



--
To unsubscribe, e-mail:   <mailto:bcel-user-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:bcel-user-help@;jakarta.apache.org>

Reply via email to