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 2004/12/20 12:13:06 UTC

Hi! Help regarding Inserting instructions in a already existing class file and updating the modified class file

Hi,
 
  I just started using BCEL, I want to instrument methods in my class
with system.out.println at start and end of methods 

Ex: 

[1]
public class HelloBCEL { 

public static void main(String[] argv) { 
String name = null;
try { 
System.out.print("Please enter your name> "); 
name = in.readLine(); 
} catch(IOException e) { return; } 
System.out.println("Hello, " + name); } 
} 

I want to instrument all the methods of above class with
system.out.println("starting") at the start and
system.out.println("ending") at the end, that is something which looks
like this

[2]
public static void main(String[] argv) { 
System.out.println("starting");
String name = null;
try { 
System.out.print("Please enter your name> "); 
name = in.readLine(); 
} catch(IOException e) { return; } 
System.out.println("Hello, " + name); } 
System.out.println("ending");
} 

So i have used BCEL and written a clas which updates the class [1]  into
class [2], The BCEL code written to insert statements is written as
follows



import java.io.*;
import org.apache.bcel.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;

public class insertBCEL{

public static ObjectType p_stream  = null;

	 public static void main( String args[] ) throws IOException {

		    ClassParser cparse = new
ClassParser("HelloBCEL.class");

		    JavaClass clazz = cparse.parse();

		    ClassGen cg = new ClassGen(clazz);

		    ConstantPool cp1 = clazz.getConstantPool();

		    ConstantPoolGen cp = new ConstantPoolGen(cp1); 
		
		    InstructionFactory factory = new
InstructionFactory(cp);
  
		    p_stream = new ObjectType("java.io.PrintStream");
			
		    Method[] meths = clazz.getMethods();

		    for(int i = 0; i< meths.length; i++ ){

			Code code = meths[i].getCode(); 

			if(code != null) 
			System.out.println(code); 

			System.out.println(meths[i]); 

	 	      meths[i] =
instrumentMeths(clazz,meths[i],cp,factory);

			Code code1 = meths[i].getCode(); 

			if(code1 != null) 			
			System.out.println(code1); 
		}
			
			
		 try {
		    cg.getJavaClass().dump("HelloBCEL.class");
		    }catch(Exception e){System.out.println(e);} 
	}


		public static Method instrumentMeths(JavaClass clazz,
Method method ,ConstantPoolGen cp, InstructionFactory factory){

			MethodGen mg = new
MethodGen(method,clazz.getClassName(),cp);

			InstructionList il = mg.getInstructionList();
		      InstructionHandle[] ihans  =
il.getInstructionHandles(); 

			InstructionHandle ihs = il.getStart();	
			InstructionHandle ihe = il.getEnd();
	
			InstructionList ils = new InstructionList();
			InstructionList ile = new InstructionList();
				
	
ils.append(factory.createFieldAccess("java.lang.System","out",p_stream,C
onstants.GETSTATIC));
		    	ils.append(new PUSH(cp,"starting"));
	
ils.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); 

	
ile.append(factory.createFieldAccess("java.lang.System","out",p_stream,C
onstants.GETSTATIC));
		    	ile.append(new PUSH(cp,"ending"));
	
ile.append(factory.createInvoke("java.io.PrintStream", "println",
Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); 
			    
			InstructionHandle ihss = il.insert(ihs,ils);
			il.redirectBranches(ihs, ihss); 
			InstructionHandle ihee = il.insert(ihe,ile);
			il.redirectBranches(ihe, ihee); 
			mg.setMaxStack();
			return mg.getMethod();
		}
}

Then i tried to execute the instrumented class java HelloBCEL , but it
doesnot instrument the strings "starting" and "ending" for the class,
pLease let me know if i am wrong somewhere in the above code.

  Hope that you can help me in this regard.

Thank you in advance,
Reddy.

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


Re: Hi! Help regarding Inserting instructions in a already existing class file and updating the modified class file

Posted by Andrew Huntwork <as...@huntwork.net>.
i think you need to call setMethodAt, replaceMethod, or setMethods.

http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/generic/ClassGen.html#setMethodAt(org.apache.bcel.classfile.Method,%20int)

btw, your printing technique will only work for a very specialized 
subset of methods:
- single return at end of method and
- no exceptions and
- no finally

you really want to add this code to method 1 (with code M1):
System.out.println("start");
try { M1 }
finally {System.out.println("end"); }

you should see how that compiles (using javap or something) and 
replicate it using bcel.

Koduru, Rajendra Kumar Reddy wrote:
> Hi,
>  
>   I just started using BCEL, I want to instrument methods in my class
> with system.out.println at start and end of methods 
> 
> Ex: 
> 
> [1]
> public class HelloBCEL { 
> 
> public static void main(String[] argv) { 
> String name = null;
> try { 
> System.out.print("Please enter your name> "); 
> name = in.readLine(); 
> } catch(IOException e) { return; } 
> System.out.println("Hello, " + name); } 
> } 
> 
> I want to instrument all the methods of above class with
> system.out.println("starting") at the start and
> system.out.println("ending") at the end, that is something which looks
> like this
> 
> [2]
> public static void main(String[] argv) { 
> System.out.println("starting");
> String name = null;
> try { 
> System.out.print("Please enter your name> "); 
> name = in.readLine(); 
> } catch(IOException e) { return; } 
> System.out.println("Hello, " + name); } 
> System.out.println("ending");
> } 
> 
> So i have used BCEL and written a clas which updates the class [1]  into
> class [2], The BCEL code written to insert statements is written as
> follows
> 
> 
> 
> import java.io.*;
> import org.apache.bcel.*;
> import org.apache.bcel.classfile.*;
> import org.apache.bcel.generic.*;
> 
> public class insertBCEL{
> 
> public static ObjectType p_stream  = null;
> 
> 	 public static void main( String args[] ) throws IOException {
> 
> 		    ClassParser cparse = new
> ClassParser("HelloBCEL.class");
> 
> 		    JavaClass clazz = cparse.parse();
> 
> 		    ClassGen cg = new ClassGen(clazz);
> 
> 		    ConstantPool cp1 = clazz.getConstantPool();
> 
> 		    ConstantPoolGen cp = new ConstantPoolGen(cp1); 
> 		
> 		    InstructionFactory factory = new
> InstructionFactory(cp);
>   
> 		    p_stream = new ObjectType("java.io.PrintStream");
> 			
> 		    Method[] meths = clazz.getMethods();
> 
> 		    for(int i = 0; i< meths.length; i++ ){
> 
> 			Code code = meths[i].getCode(); 
> 
> 			if(code != null) 
> 			System.out.println(code); 
> 
> 			System.out.println(meths[i]); 
> 
> 	 	      meths[i] =
> instrumentMeths(clazz,meths[i],cp,factory);
> 
> 			Code code1 = meths[i].getCode(); 
> 
> 			if(code1 != null) 			
> 			System.out.println(code1); 
> 		}
> 			
> 			
> 		 try {
> 		    cg.getJavaClass().dump("HelloBCEL.class");
> 		    }catch(Exception e){System.out.println(e);} 
> 	}
> 
> 
> 		public static Method instrumentMeths(JavaClass clazz,
> Method method ,ConstantPoolGen cp, InstructionFactory factory){
> 
> 			MethodGen mg = new
> MethodGen(method,clazz.getClassName(),cp);
> 
> 			InstructionList il = mg.getInstructionList();
> 		      InstructionHandle[] ihans  =
> il.getInstructionHandles(); 
> 
> 			InstructionHandle ihs = il.getStart();	
> 			InstructionHandle ihe = il.getEnd();
> 	
> 			InstructionList ils = new InstructionList();
> 			InstructionList ile = new InstructionList();
> 				
> 	
> ils.append(factory.createFieldAccess("java.lang.System","out",p_stream,C
> onstants.GETSTATIC));
> 		    	ils.append(new PUSH(cp,"starting"));
> 	
> ils.append(factory.createInvoke("java.io.PrintStream", "println",
> Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); 
> 
> 	
> ile.append(factory.createFieldAccess("java.lang.System","out",p_stream,C
> onstants.GETSTATIC));
> 		    	ile.append(new PUSH(cp,"ending"));
> 	
> ile.append(factory.createInvoke("java.io.PrintStream", "println",
> Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); 
> 			    
> 			InstructionHandle ihss = il.insert(ihs,ils);
> 			il.redirectBranches(ihs, ihss); 
> 			InstructionHandle ihee = il.insert(ihe,ile);
> 			il.redirectBranches(ihe, ihee); 
> 			mg.setMaxStack();
> 			return mg.getMethod();
> 		}
> }
> 
> Then i tried to execute the instrumented class java HelloBCEL , but it
> doesnot instrument the strings "starting" and "ending" for the class,
> pLease let me know if i am wrong somewhere in the above code.
> 
>   Hope that you can help me in this regard.
> 
> Thank you in advance,
> Reddy.
> 
> ---------------------------------------------------------------------
> 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