> Hi,
>
> I'm forwarding a mail regarding bytecode
> instrumentation, more specifically "encapsulating a
> method body in a try-finally block" through dynamic
> instrumentation. I'm forwarding it to the archiving
> list for two reasons: first, it will help others who
> wants to know about it & second, for experts who can
> correct us in case there is some thing wrong in it.
Hi
I have read the proposed modification, but i have to remark that this
won't work that easily.
The critical point is, that bytecode has to fullfill strict constraints.
Or the verifier will reject it.
[...]
>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.
Simply try catch the whole method body isn't possible in general,
if the method stores unitialized objects in local variables this
strategy will fail.
(JVMSPEC)# There must never be an uninitialized class instance on the
operand stack or in a local variable when any backwards branch is taken.
There must never be an uninitialized class instance in a local variable
in code protected by an exception handler. However, an uninitialized
class instance may be on the operand stack in code protected by an
exception handler. When an exception is thrown, the contents of the
operand stack are discarded.
>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));
> }
Again it's not that simple, If you use a nice compiler this will work,
but there is no guarantee that the stack will contain a single item when
returning.
If some stack items are discarded through return, then this simple jump
will lead to a constraint violation.
This only happens with compilers that optimize, and the sun compiler
even produces dead code, so you don't have to fear it will ever produce
something like that.
(JVMSPEC)# If an instruction can be executed along several different
execution paths, the operand stack must have the same depth (�3.6.2)
prior to the execution of the instruction, regardless of the path taken.
--
To unsubscribe, e-mail: <mailto:bcel-user-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:bcel-user-help@;jakarta.apache.org>