You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bcel-user@jakarta.apache.org by "Koduru, Rajendra Kumar Reddy" <ra...@sap.com> on 2005/02/04 21:07:22 UTC

Please help me regarding finally block

Hi All, 
	
	Currently i am planning to instrument each method of a class
dynamically with system.out.println() statements.
	
	as it is not possible to get it executed, due to the return
statements which are available in middle of method, 

	As seen from many sources, implementing it with try and finally
is a good idea.

	finally seems to be more complex to handle compared to catch
(atleast to me).

	however i got the source from internet, i could not understand
few things in the source, could some one please clarify me.

	i have directly put put my understandings and queries in the
middle of code IN CAPS, [code is given below, of course not too big]. So
please correct me and help me in this regard.

Thank you
Reddy



public void instrumentMethod (ClassGen cg, MethodGen mg)
	{
		InstructionList il = mg.getInstructionList();

		InstructionFactory ifact = new InstructionFactory(cg);

		InstructionHandle start = il.getStart();
		InstructionHandle end = il.getEnd();


		//  IN THE FOLLOWING SNIPPET OF CODE, CALL TO
SUBROUTINES ARE INSERTED AND ALL THE TARGETS OF RETURN INSTRUCTIONS ARE
CHANGED

		Collection<JSR> jsrs = new ArrayList<JSR>();
		for (Iterator i = il.iterator(); i.hasNext(); ) {
			InstructionHandle ih =
(InstructionHandle)i.next();

			if (ih.getInstruction() instanceof RETURN) {
				JSR jsr2 = new JSR(null);
				jsrs.add(jsr2);
				InstructionHandle n = il.insert(ih,
jsr2);
							
				il.redirectBranches(ih, n);
			}
		}

		// END OF ABOVE UNDERSTANDING. AM I CORRECT ??

		
		
		InstructionHandle h1 = il.append(new ASTORE(0)); // AT
THE CURRENT SITUATION, WHAT IS ON THE TOP OF STACK AND WHY IS IT
STORED??

		JSR jsr = new JSR(null);
// WHY A SUBROUTINE CALL IS DONE HERE??? 

		jsrs.add(jsr);
		il.append(jsr);

		InstructionHandle h2 = il.append(new ALOAD(0));	  //
REFLECTS THE ABOVE STORE OPERATION; SO WHAT IS ACTUALLY IN THIS NOW??

		il.append(new ATHROW());
// I THINK IT IS TO RETHROW THE EXCEPTION IF AN EXCEPTION ARISES

		InstructionHandle handler = il.append(new ASTORE(1)); //
STORES THE EXCEPTION VARIABLE

		// I WILL APPEND AN PRINTLN STATEMENT HERE 

		il.append(new RET(1));
// RETURNING FROM SUBROUTINE, BUT DOESNT THE INDEX OF RET START AT 0

		for (JSR j : jsrs) {
			j.setTarget(handler);
		}	

		mg.addExceptionHandler(start, end, h1, null);	//
DOESNT THE EXCEPTION HANDLER START AT HANDLE handler(which is just 3
lines above in this code)

		il.setPositions(true);
//  IS THIS NECESSARY ??
	}



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


Re: Please help me regarding finally block

Posted by Andrew Huntwork <as...@huntwork.net>.
Koduru, Rajendra Kumar Reddy wrote:
> 		//  IN THE FOLLOWING SNIPPET OF CODE, CALL TO
> SUBROUTINES ARE INSERTED AND ALL THE TARGETS OF RETURN INSTRUCTIONS ARE
> CHANGED

returns are not targeters.  what you're redirecting below are things 
that target return.  you want things that jump directly to the return to 
jump to the jsr instead.  that way the jsr will be executed whenever the 
return is executed.

> 
> 		Collection<JSR> jsrs = new ArrayList<JSR>();
> 		for (Iterator i = il.iterator(); i.hasNext(); ) {
> 			InstructionHandle ih =
> (InstructionHandle)i.next();
> 
> 			if (ih.getInstruction() instanceof RETURN) {
> 				JSR jsr2 = new JSR(null);
> 				jsrs.add(jsr2);
> 				InstructionHandle n = il.insert(ih,
> jsr2);
> 							
> 				il.redirectBranches(ih, n);
> 			}
> 		}
> 
> 		// END OF ABOVE UNDERSTANDING. AM I CORRECT ??
> 
> 		
> 		
> 		InstructionHandle h1 = il.append(new ASTORE(0)); // AT
> THE CURRENT SITUATION, WHAT IS ON THE TOP OF STACK AND WHY IS IT
> STORED??

you are inserting a try/catch around the entire original function to 
implement finally.  h1 is the handler.  an exception handler is executed 
with the Throwable on the stack, and that's what you're storing in lv 0.

> 
> 		JSR jsr = new JSR(null);
> // WHY A SUBROUTINE CALL IS DONE HERE??? 

the basic idea of finally is that you insert one subroutine that will be 
executed before the function exits by any path.  the possible exit paths 
are:  all of the return instructions and an uncaught exception.  we took 
care of calling the subroutine from the return instructions above.  now 
we're taking care of exits via uncaught exceptions.  this block catches 
all exceptions, calls the subroutine, and re-throws the exception.

> 
> 		jsrs.add(jsr);
> 		il.append(jsr);
> 
> 		InstructionHandle h2 = il.append(new ALOAD(0));	  //
> REFLECTS THE ABOVE STORE OPERATION; SO WHAT IS ACTUALLY IN THIS NOW??

here we load the exception we caught and stored at the beginning of the 
block and re-throw it

> 
> 		il.append(new ATHROW());
> // I THINK IT IS TO RETHROW THE EXCEPTION IF AN EXCEPTION ARISES

yep

> 
> 		InstructionHandle handler = il.append(new ASTORE(1)); //
> STORES THE EXCEPTION VARIABLE

no.  a subroutine is executed with the return address on the stack. 
this is a special jvm type.  that's what we're storing here.

> 
> 		// I WILL APPEND AN PRINTLN STATEMENT HERE 

good.  this is the right place for it.

> 
> 		il.append(new RET(1));
> // RETURNING FROM SUBROUTINE, BUT DOESNT THE INDEX OF RET START AT 0

the argument to ret is a local variable index containing a return 
address.  Thus, jsr and ret are assymetric.  one puts a return address 
onto the stack, and the other loads it from a local variable.  whatever.

> 
> 		for (JSR j : jsrs) {
> 			j.setTarget(handler);
> 		}	
> 
> 		mg.addExceptionHandler(start, end, h1, null);	//
> DOESNT THE EXCEPTION HANDLER START AT HANDLE handler(which is just 3
> lines above in this code)

see above re:  catching and re-throwing all uncaught exceptions.

> 
> 		il.setPositions(true);
> //  IS THIS NECESSARY ??

i don't know, but just to be safe i'd at least call il.setPositions();

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

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