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 "Nikhil C. Khedkar" <ni...@yahoo.com> on 2004/02/18 10:58:04 UTC

Constructor Instrumentation : super()

Hi,
	I have a query regarding the instrumentation of the
constructor. I have read all the archived mail in this
regard, but none of them served useful. I have the
same requirement i.e. put a method call at each method
start and method end. Have already put a try catch for
that. Now the task is to skip super() call before I
put my method call in the constructor.
	
	I have a code that works for 99% of the cases. 
	
	for(int j = 1; j < ihs.length; j++)
	{
		if(ihs[j].getInstruction() instanceof INVOKESPECIAL)
		{
			il.append(ihs[j], instrumentedPatchList);
			break;
		}
	}
	
	It works for 
	
	1)public ABCD(XYZ obj)
	{
		super(obj);
	}
	
	Now a more complicated case
	
	2)public RuleTree(int type, AppCodeAnalyzerMainPanel
mainPanel)
	{
		super(new DefaultTreeModel(new RuleNode("Rules")));
		method1();
		method2();
	}
	
	The above code fails because the Special Instruction
is not at first position. Hence A refined approach
will be to get the first instruction handle of the
second line in the constructor (first instruction
handle for method1()). Now I scan all the instructions
of the first line (super(new DefaultTreeModel(new
RuleNode("Rules")))). If there is any INVOKESPECIAL in
this list I put my code at the end of first line. This
thing works fine.
	
	A bit more complex case
	
	3)private XYZHandler(EventHandler commandHandler)
	{
		super(
			ABCD.getInstance(),
			Helper.getInstance(),
			commandHandler,
			100);
		method1();
	}
	
	Now the above mentioned approach doesn't work and I
end up putting my method call before super() and get
VerifyError. Has anyone (especially the ones who have
posted those questions on constructor instrumentation
previously) been able to build a fullproof code?
	
Thanks,
	Nikhil Khedkar

__________________________________
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.
http://antispam.yahoo.com/tools

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


Re: Intrumenting methods local variable indices

Posted by Andrew Huntwork <as...@huntwork.net>.
eek, i should read code more carefully (or i should be more fully 
awake), you're totally correct about not needing to call setMaxLocals. 
Thanks for showing me the error of my ways :).  but it's still risky to 
trust the local variable table.  I'm pretty sure it's just for symbolic 
debuggers, and even if the lvt is present and correct according to the 
jvm spec 
(http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#5957), 
there's no guarantee that the lvt entries completely cover the live 
ranges of the local variable.

dweimers@students.cs.uu.nl wrote:
>>it seems that: a) bcel in fact does not look at variable scopes when
>>giving you a local variable number; and b) it doesn't adjust max_locals
>>when giving you a local variable, so you'll have to call setMaxLocals
>>even if you use this technique
> 
> 
> According to lines 288-291 the max_locals is adjusted when necessary. For
> this to work a consistant/valid max_locals should be present because this
> is used so calling setMaxLocals() before calling addLocalVariable() would
> be good idea. So if local variables are only added by calling
> addLocalVariable an invocation of setMacLocals() could be omitted, I
> think.
> 
> 288:      int  add = type.getSize();
> 289:
> 290:      if(slot + add > max_locals)
> 291:	    max_locals = slot + add;
> 
> I think the misunderstanding is raised by the fact that the max_locals int
> value is used as the next index and thus is actualy 1 higher (getMaxLocals
> returns int n, thus the slots 0 to n-1 are taken and the next is n)
> 
> 
>>I'm pretty sure the start and end arguments to addLocalVariable are
>>required becuase this info ends up in the local variable table for the
>>method, not becuase bcel has any interest in knowing internally where
>>particula rvariables are in scope.
>>also, your code uses start == null and end == null in addLocalVariable,
>>so even if bcel took scopes into account in assigning lv indices, it
>>would have to assign different indices to sss and rrr.
> 
> 
> Yeah that's true, indeed. The BCEL developers could solve this by using
> the convention that getIndex() can only succeed if both scope boundaries
> are set and otherwise raise an exception or something.
> 
> ---------------------------------------------------------------------
> 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


Re: Intrumenting methods local variable indices

Posted by dw...@students.cs.uu.nl.
> it seems that: a) bcel in fact does not look at variable scopes when
> giving you a local variable number; and b) it doesn't adjust max_locals
> when giving you a local variable, so you'll have to call setMaxLocals
> even if you use this technique

According to lines 288-291 the max_locals is adjusted when necessary. For
this to work a consistant/valid max_locals should be present because this
is used so calling setMaxLocals() before calling addLocalVariable() would
be good idea. So if local variables are only added by calling
addLocalVariable an invocation of setMacLocals() could be omitted, I
think.

288:      int  add = type.getSize();
289:
290:      if(slot + add > max_locals)
291:	    max_locals = slot + add;

I think the misunderstanding is raised by the fact that the max_locals int
value is used as the next index and thus is actualy 1 higher (getMaxLocals
returns int n, thus the slots 0 to n-1 are taken and the next is n)

> I'm pretty sure the start and end arguments to addLocalVariable are
> required becuase this info ends up in the local variable table for the
> method, not becuase bcel has any interest in knowing internally where
> particula rvariables are in scope.
> also, your code uses start == null and end == null in addLocalVariable,
> so even if bcel took scopes into account in assigning lv indices, it
> would have to assign different indices to sss and rrr.

Yeah that's true, indeed. The BCEL developers could solve this by using
the convention that getIndex() can only succeed if both scope boundaries
are set and otherwise raise an exception or something.

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


Re: Intrumenting methods local variable indices

Posted by Andrew Huntwork <as...@huntwork.net>.
check it out:

http://jakarta.apache.org/bcel/xref/org/apache/bcel/generic/MethodGen.html#321
and
http://jakarta.apache.org/bcel/xref/org/apache/bcel/generic/MethodGen.html#282

it seems that: a) bcel in fact does not look at variable scopes when 
giving you a local variable number; and b) it doesn't adjust max_locals 
when giving you a local variable, so you'll have to call setMaxLocals 
even if you use this technique

I'm pretty sure the start and end arguments to addLocalVariable are 
required becuase this info ends up in the local variable table for the 
method, not becuase bcel has any interest in knowing internally where 
particula rvariables are in scope.

btw, sun's jvm does not require that the local variable table makes any 
sense, or is internally consistent, or correct, or even present, when 
running a class, and i'm pretty sure you can tell javac not to produce a 
lv table.  So it's kind of risky to base the correctness of your 
generated code o nthe correctness of the lv table in the input code.

also, your code uses start == null and end == null in addLocalVariable, 
so even if bcel took scopes into account in assigning lv indices, it 
would have to assign different indices to sss and rrr.

dweimers@students.cs.uu.nl wrote:
>>you could just use MethodGen.getMaxLocals() as a local variable number
>>that is not used throughout the method.  Make sure you keep getMaxLocals
>>up to date by calling setMaxLocals when appropriate.
> 
> 
> That is indeed a solution but the manually calling setMaxLocals leaves a
> bad taste in my mouth (this is just something that I'll forget).
> 
> When I was browsing the API I ran into the addLocalVariable method of
> MethodGen that does what I want, but I it seems that it doesn't really
> take into account scopes of local variables. Consider the following code:
> 
> public double foo (int i, double d, int ii, double dd)
> {
>   {//scope block 1
>    String sss = "NEW SSS";
>    System.out.println(sss);
>   }
>   {//scope block 2
>    String rrr = "NEW RRR";
>    System.out.println(rrr);
>   }
>   return i + d + ii + dd;
> }
> 
> I think we all can agree that the size of the local variables at the
> beginning of the body is 7 {0=this, 1=i, 2-3=d, 4=ii, 5-6=dd} so the
> variable sss should be stored at position 7 which is the 8th slot, but
> since the scope blocks are used that location should be reused to store
> variable rrr.
> 
> When compiling this code with javac 1.4.2 it'll nicely generate the
> following for the two scope blocks and reuses the slot for the local
> variables sss and rrr:
> 
>    0 ldc #25 <String "NEW SSS">
>    2 astore 7
>    4 getstatic #11 <Field java.io.PrintStream out>
>    7 aload 7
>    9 invokevirtual #16 <Method void println(java.lang.String)>
>   12 ldc #26 <String "NEW RRR">
>   14 astore 7
>   16 getstatic #11 <Field java.io.PrintStream out>
>   19 aload 7
>   21 invokevirtual #16 <Method void println(java.lang.String)>
>   <...> cut out
> 
> Local variables for method double foo(int, double, int, double)
>    ClassB this  pc=0, length=36, slot=0
>    int i  pc=0, length=36, slot=1
>    double d  pc=0, length=36, slot=2
>    int ii  pc=0, length=36, slot=4
>    double dd  pc=0, length=36, slot=5
>    java.lang.String sss  pc=4, length=8, slot=7
>    java.lang.String rrr  pc=16, length=8, slot=7
> 
> But using the BCEL API to instrument the two scope blocks into an existing
> method using this code:
> 
>             //sss
>             LocalVariableGen lg = mg.addLocalVariable("sss", Type.STRING,
> null, null);
>             int sss = lg.getIndex();
>             print.append(new PUSH(_cp, "NEW SSS"));
>             print.append(_factory.createStore(Type.STRING, sss)); // "sss"
> valid from here
>             lg.setStart(print.append(_factory.createFieldAccess("java.lang.System",
> "out", new ObjectType("java.io.PrintStream"),
> Constants.GETSTATIC)));
>             print.append(_factory.createLoad(Type.OBJECT, sss));
>             lg.setEnd(print.append(_factory.createInvoke("java.io.PrintStream",
> "println", Type.VOID, new Type[] { Type.STRING },
> Constants.INVOKEVIRTUAL)));
>             //rrr
>             lg = mg.addLocalVariable("rrr", Type.STRING, null, null);
>             int rrr = lg.getIndex();
>             print.append(new PUSH(_cp, "NEW RRR"));
>             print.append(_factory.createStore(Type.STRING, rrr)); // "rrr"
> valid from here
>             lg.setStart(print.append(_factory.createFieldAccess("java.lang.System",
> "out", new ObjectType("java.io.PrintStream"),
> Constants.GETSTATIC)));
>             print.append(_factory.createLoad(Type.OBJECT, rrr));
>             lg.setEnd(print.append(_factory.createInvoke("java.io.PrintStream",
> "println", Type.VOID, new Type[] { Type.STRING },
> Constants.INVOKEVIRTUAL)));
> 
> also works fine, but does not take into account the fact that the scopes
> and yields:
> 
> Method double foo(int, double, int, double)
>    0 ldc #90 <String "NEW SSS">
>    2 astore 7
>    4 getstatic #11 <Field java.io.PrintStream out>
>    7 aload 7
>    9 invokevirtual #16 <Method void println(java.lang.String)>
>   12 ldc #92 <String "NEW RRR">
>   14 astore 8
>   16 getstatic #11 <Field java.io.PrintStream out>
>   19 aload 8
>   21 invokevirtual #16 <Method void println(java.lang.String)>
>   <...> cut out
> 
> Local variables for method double foo(int, double, int, double)
>    ClassB this  pc=24, length=12, slot=0
>    int i  pc=24, length=12, slot=1
>    double d  pc=24, length=12, slot=2
>    int ii  pc=24, length=12, slot=4
>    double dd  pc=24, length=12, slot=5
>    java.lang.String sss  pc=4, length=8, slot=7
>    java.lang.String rrr  pc=16, length=8, slot=8
> 
> and thus does not reuse the slot, which it should! Is this a bug? Is this
> a feature? If it is shouldn't this be documented? What is the use of
> setting the 'begin' and 'end' InstructionHandles if they are not used?
> 
> 
> 
> ---------------------------------------------------------------------
> 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


Re: Intrumenting methods local variable indices

Posted by dw...@students.cs.uu.nl.
> you could just use MethodGen.getMaxLocals() as a local variable number
> that is not used throughout the method.  Make sure you keep getMaxLocals
> up to date by calling setMaxLocals when appropriate.

That is indeed a solution but the manually calling setMaxLocals leaves a
bad taste in my mouth (this is just something that I'll forget).

When I was browsing the API I ran into the addLocalVariable method of
MethodGen that does what I want, but I it seems that it doesn't really
take into account scopes of local variables. Consider the following code:

public double foo (int i, double d, int ii, double dd)
{
  {//scope block 1
   String sss = "NEW SSS";
   System.out.println(sss);
  }
  {//scope block 2
   String rrr = "NEW RRR";
   System.out.println(rrr);
  }
  return i + d + ii + dd;
}

I think we all can agree that the size of the local variables at the
beginning of the body is 7 {0=this, 1=i, 2-3=d, 4=ii, 5-6=dd} so the
variable sss should be stored at position 7 which is the 8th slot, but
since the scope blocks are used that location should be reused to store
variable rrr.

When compiling this code with javac 1.4.2 it'll nicely generate the
following for the two scope blocks and reuses the slot for the local
variables sss and rrr:

   0 ldc #25 <String "NEW SSS">
   2 astore 7
   4 getstatic #11 <Field java.io.PrintStream out>
   7 aload 7
   9 invokevirtual #16 <Method void println(java.lang.String)>
  12 ldc #26 <String "NEW RRR">
  14 astore 7
  16 getstatic #11 <Field java.io.PrintStream out>
  19 aload 7
  21 invokevirtual #16 <Method void println(java.lang.String)>
  <...> cut out

Local variables for method double foo(int, double, int, double)
   ClassB this  pc=0, length=36, slot=0
   int i  pc=0, length=36, slot=1
   double d  pc=0, length=36, slot=2
   int ii  pc=0, length=36, slot=4
   double dd  pc=0, length=36, slot=5
   java.lang.String sss  pc=4, length=8, slot=7
   java.lang.String rrr  pc=16, length=8, slot=7

But using the BCEL API to instrument the two scope blocks into an existing
method using this code:

            //sss
            LocalVariableGen lg = mg.addLocalVariable("sss", Type.STRING,
null, null);
            int sss = lg.getIndex();
            print.append(new PUSH(_cp, "NEW SSS"));
            print.append(_factory.createStore(Type.STRING, sss)); // "sss"
valid from here
            lg.setStart(print.append(_factory.createFieldAccess("java.lang.System",
"out", new ObjectType("java.io.PrintStream"),
Constants.GETSTATIC)));
            print.append(_factory.createLoad(Type.OBJECT, sss));
            lg.setEnd(print.append(_factory.createInvoke("java.io.PrintStream",
"println", Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL)));
            //rrr
            lg = mg.addLocalVariable("rrr", Type.STRING, null, null);
            int rrr = lg.getIndex();
            print.append(new PUSH(_cp, "NEW RRR"));
            print.append(_factory.createStore(Type.STRING, rrr)); // "rrr"
valid from here
            lg.setStart(print.append(_factory.createFieldAccess("java.lang.System",
"out", new ObjectType("java.io.PrintStream"),
Constants.GETSTATIC)));
            print.append(_factory.createLoad(Type.OBJECT, rrr));
            lg.setEnd(print.append(_factory.createInvoke("java.io.PrintStream",
"println", Type.VOID, new Type[] { Type.STRING },
Constants.INVOKEVIRTUAL)));

also works fine, but does not take into account the fact that the scopes
and yields:

Method double foo(int, double, int, double)
   0 ldc #90 <String "NEW SSS">
   2 astore 7
   4 getstatic #11 <Field java.io.PrintStream out>
   7 aload 7
   9 invokevirtual #16 <Method void println(java.lang.String)>
  12 ldc #92 <String "NEW RRR">
  14 astore 8
  16 getstatic #11 <Field java.io.PrintStream out>
  19 aload 8
  21 invokevirtual #16 <Method void println(java.lang.String)>
  <...> cut out

Local variables for method double foo(int, double, int, double)
   ClassB this  pc=24, length=12, slot=0
   int i  pc=24, length=12, slot=1
   double d  pc=24, length=12, slot=2
   int ii  pc=24, length=12, slot=4
   double dd  pc=24, length=12, slot=5
   java.lang.String sss  pc=4, length=8, slot=7
   java.lang.String rrr  pc=16, length=8, slot=8

and thus does not reuse the slot, which it should! Is this a bug? Is this
a feature? If it is shouldn't this be documented? What is the use of
setting the 'begin' and 'end' InstructionHandles if they are not used?



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


Re: Intrumenting methods local variable indices

Posted by Andrew Huntwork <as...@huntwork.net>.
you could just use MethodGen.getMaxLocals() as a local variable number 
that is not used throughout the method.  Make sure you keep getMaxLocals 
up to date by calling setMaxLocals when appropriate.

dweimers@students.cs.uu.nl wrote:
> Hi,so I have been playing with BCEL for a couple of weeks now and it works
> really nice, but I have the following problem:
> 
> Consider this java code:
> 
> 
> void foo(int x)
> {
>   String a = "aa";
>   [x] -> localvariables(0=x,1=a) so I need to use 2 and 3
>   somemethod();
> 
>   String b = "bb";
>   [y] -> localvariables(0=x,1=a,2=b) so I need to use 3 and 4
>   someOthermethod();
> }
> 
> What I need to do is instrument some synchronized blocks around the methods,
> but the thing is that synchronization code will need local variables to
> store various values such as the actual monitor object and another for
> exception handling to ensure that the monitor is released when something bad
> happens. So in the end the code I am going to instrument 'around' something
> needs 2 local variable spaces, but ofcourse I don't want to overwrite
> anything. How can I do this nicely? It would be great if there would be a
> method like getCurrentLocalVariableIndex that would return 1 at [x] and 2 at
> [y] but I couldn't find such a thing in the API doc, but there should be
> some nice solution to this so, any suggestions?
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: bcel-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: bcel-user-help@jakarta.apache.org
> 

-- 
"I say to you that the VCR is to the American film
producer and the American public as the Boston
strangler is to the woman home alone."
         -Jack Valenti, President, Motion Picture
          Association of America, Inc., before
          The House Subcommittee on Courts, Civil
          Liberties, and The Administration of
          Justice, August, 1982,
          http://cryptome.org/hrcw-hear.htm


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


Intrumenting methods local variable indices

Posted by dw...@students.cs.uu.nl.
Hi,so I have been playing with BCEL for a couple of weeks now and it works
really nice, but I have the following problem:

Consider this java code:


void foo(int x)
{
  String a = "aa";
  [x] -> localvariables(0=x,1=a) so I need to use 2 and 3
  somemethod();

  String b = "bb";
  [y] -> localvariables(0=x,1=a,2=b) so I need to use 3 and 4
  someOthermethod();
}

What I need to do is instrument some synchronized blocks around the methods,
but the thing is that synchronization code will need local variables to
store various values such as the actual monitor object and another for
exception handling to ensure that the monitor is released when something bad
happens. So in the end the code I am going to instrument 'around' something
needs 2 local variable spaces, but ofcourse I don't want to overwrite
anything. How can I do this nicely? It would be great if there would be a
method like getCurrentLocalVariableIndex that would return 1 at [x] and 2 at
[y] but I couldn't find such a thing in the API doc, but there should be
some nice solution to this so, any suggestions?

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


Re: Byte code coverage -- unusual constructions

Posted by Andrew Huntwork <as...@huntwork.net>.
we needed a kind of representative sample of classes recently, so we 
wrote this spider type thing.  It got us 13GB of jars, which is probably 
a pretty good (maybe too good) variety.  We have tested some of our 
transformations on a small subset of these files by running the 
transformation, then doing Class.forName("foo",false 
/*<-important*/,getClass().getClassLoader()) on each class in the 
transformed jar to see if all the classes still verify.  There was 
enough weird code in there to keep us busy bug fixing for a while, but I 
really don't think it's exhaustive.  (Hint:  some of the classes you get 
won't verify even before you mess with them)

Feel free to do whatever you want to with this code.  It uses the google 
api, which you can find out about at http://www.google.com/apis/. 
You'll need to replace "GET YOUR OWN KEY" below with your own key...

import java.util.*;
import java.io.*;
import java.net.*;
import com.google.soap.search.*;

public class JarFinder{
    public static void main(String args[]){
       GoogleSearch search = new GoogleSearch();
       search.setKey("GET YOUR OWN KEY");
       search.setQueryString("\"index of\" jar");
       GoogleSearchResultElement[] elements = null;

       PrintStream logout = null;
       try{
          logout = new PrintStream(new FileOutputStream("jarlog.out"));
       }catch(Exception ex){
          System.err.println("Error opening log output file");
          return;
       }

       HashSet gotten = new HashSet();
       int index=0;
       do{
          search.setStartResult(index);
          index+=10;
          try{
             elements = search.doSearch().getResultElements();
          }catch(Exception ex){
             System.err.println("Search failed");
             return;
          }

          System.err.println("Got "+elements.length+" results");

          for (int i=0;i<elements.length;i++){
             Vector lines = new Vector(1000);

             try{
                BufferedReader input =
                   new BufferedReader
                   (new InputStreamReader
                    (new URL
                     (elements[i].getURL()).openStream()));
                String line=null;
                while((line=input.readLine())!=null)
                   lines.add(line);
                input.close();
             }catch(Exception ex){
                System.err.println("Error connecting or reading from 
"+elements[i].getURL());
             }

             for (int j=0;j<lines.size();j++){
                String line = (String)lines.get(j);
                for (java.util.Iterator jarurls=
                        getAllURLs(line, 
elements[i].getURL()).iterator();jarurls.hasNext();){

                   String jar = (String)jarurls.next();
                   String savename = jar;
                   if (savename.indexOf('/')!=-1)
                      savename = 
savename.substring(savename.lastIndexOf('/')+1);
                   if (gotten.contains(savename)){
                      System.err.println("Skipping "+savename+" (already 
got one!)");
                      continue;
                   }
                   System.err.println("Saving "+jar+" as "+savename);

                   InputStream jarinput = null;
                   FileOutputStream fout = null;

                   try{
                      jarinput = new URL(jar).openStream();
                      fout = new FileOutputStream(savename);
                      byte[] bytes=new byte[1048576];
                      int numread=0;
                      while((numread=jarinput.read(bytes))>0){
                         fout.write(bytes, 0, numread);
                      }
                      jarinput.close();
                      fout.close();
                   }catch(Exception ex){
                      System.err.println("Error preparing jarfile for 
download: "+jar);
                      continue;
                   }

                   gotten.add(savename);
                   logout.println(jar+" saved as "+savename);
                }
             }
          }

       }while(elements.length==10);

       try{
          logout.close();
       }catch(Exception ex){}
    }

    private static HashSet getAllURLs(String line, String resulturl){
       HashSet results = new HashSet();

       String lowerline=line.toLowerCase();
       int start=0;
       for (int result=lowerline.indexOf("href", start); result!=-1; 
result=lowerline.indexOf("href", start)){
          start=result+4;
          int qstart=line.indexOf("\"", result);
          if (qstart==-1)
             continue;
          int qend=line.indexOf("\"", qstart+1);
          if (qend==-1)
             continue;

          String jarname = line.substring(qstart+1, qend);
          if (jarname.toLowerCase().endsWith(".jar")){
             if (!(jarname.startsWith("http://") ||
                   jarname.startsWith("https://") ||
                   jarname.startsWith("ftp://"))){
                jarname = resulturl.substring(0, 
resulturl.lastIndexOf('/')+1)+jarname;
             }

             results.add(jarname);
             start=qend+1;
          }
       }
       return results;
    }
}

Bil Lewis wrote:
> I find that the instrumentation I do is generally fine,
> but subject to odd little quirks that some compilers (or
> other instrumentation tools) produce.
> 
> I only have the javac on Apple to work with and I *seem*
> to have complete coverage of what it produces, but I
> notice now and then that other compilers produce different
> byte code and that I sometimes mess up on this code
> because I've never seen it before.
> 
> So my question is: "Do we have a collection of class files
> that give wide coverage of all the possible orderings for byte
> codes?"
> 
> -Bil
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: bcel-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: bcel-user-help@jakarta.apache.org
> 

-- 
"I say to you that the VCR is to the American film
producer and the American public as the Boston
strangler is to the woman home alone."
         -Jack Valenti, President, Motion Picture
          Association of America, Inc., before
          The House Subcommittee on Courts, Civil
          Liberties, and The Administration of
          Justice, August, 1982,
          http://cryptome.org/hrcw-hear.htm


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


Byte code coverage -- unusual constructions

Posted by Bil Lewis <bi...@bayarea.net>.
I find that the instrumentation I do is generally fine,
but subject to odd little quirks that some compilers (or
other instrumentation tools) produce.

I only have the javac on Apple to work with and I *seem*
to have complete coverage of what it produces, but I
notice now and then that other compilers produce different
byte code and that I sometimes mess up on this code
because I've never seen it before.

So my question is: "Do we have a collection of class files
that give wide coverage of all the possible orderings for byte
codes?"

-Bil




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


Re: Constructor Instrumentation : super()

Posted by Andrew Huntwork <as...@huntwork.net>.
Erik Corry wrote:
> On Wed, Feb 18, 2004 at 02:59:24PM -0700, Andrew Huntwork wrote:
> 
>>Depending on what 
>>kind of instrumentation you want to do, this is sufficient.  For 
>>example, if you just want to know a complete call trace, you can insert 
>>the bytecode equivalent of the following at every method entry and exit:
>>
>>log("entering/leaving foo.bar()V");
> 
> 
> Except that you can't do that right at entry of the constructor
> (before the call to the superclass constructor).  Try it.  Or
> look at the code in the Helloifier:

It would seem that you can.  See test.<init>:
    0 ldc #1 <String "foo">
    2 invokestatic #44 <Method void log(java.lang.String)>
    5 aload_0
    6 invokespecial #42 <Method p()>
    9 return

It seems to verify.  I also just did a similar thing to every method in 
SpecJVM, and it still ran correctly. I think there aren't really that 
many restrictions on what you can do in a constructor.  you just can't 
treat 'this' as an object until you make it one by calling super().

> 
> http://cvs.sourceforge.net/viewcvs.py/bcel/BCEL/helloify.java?view=markup
> 
> Look for "init".  The code is there for a reason, and it's not
> sufficient.

I'd be interested to see an example where inserting ldc invokestatic at 
the beginning of <init> leads to unverifiable code.  Maybe something to 
do with exceptions (since they screw everything up)?  The example is 
pretty old code.  Maybe Mr. Dahm was working around some bug in bcel? 
cvs history doesn't really tell me anything here.

> 
> 
>>>>Second, you could do some pretty complicated stack and control flow 
>>>>analysis.  Here's something that's legal in bytecode but not in java:
>>>>
>>>>if(...)
>>>>super(foo);
>>>>else
>>>>super(bar);
>>>
>>>
>>>Are you sure that's legal?  The VM spec says:
>>>
>>>   "If a constructor body does not begin with an explicit
>>>   constructor invocation and the constructor being declared
>>>   is not part of the primordial class Object, then the
>>>   constructor body is implicitly assumed by the compiler to
>>>   begin with a superclass constructor invocation "super();",
>>>   an invocation of the constructor of the direct superclass
>>>   that takes no arguments."
>>>
>>>Does you example begin with an explicit constructor invocation?
>>>I don't think it does.  Is it allowed to call two different
>>>constructors for the same class on an object?
>>
>>As I say, not legal in Java (which your passage refers to), but totally 
>>legal in bytecode.
> 
> 
> My passage refers to the VM spec, so it's about byte code, not
> about the Java language.

but it's talking about how to compile this kind of code ("implicitly 
assumed by the compiler to begin with ..."), and it's in a chapter (2) 
called "Java Programming Language Concepts"...

> 
> 
>>The attached class has this <init>:
>>
>>Method test()
>>   0 iconst_0
>>   1 ifeq 11
>>   4 aload_0
>>   5 invokespecial #10 <Method java.lang.Object()>
>>   8 goto 15
>>  11 aload_0
>>  12 invokespecial #10 <Method java.lang.Object()>
>>  15 return
>>
>>it verifies just fine
> 
> 
> OK.  I never would have guessed from the spec.
> 
> 
>>>Does anyone do that?
>>
>>[No concrete examples mentioned]

A slightly different question is, how sure are you that your code will 
never be run on code that looks like my example?  I recently saw a talk 
by Chad Woolley, the www.virtualmock.org guy. 
(http://www.virtualmock.org/presentations/)  Apparently, he gets a 
chance to see how various bcel-derived programs worked together, 
including aspect-oriented tools (aspectj.org) and tools that figure out 
what parts of your code are executed by a test suite (code coverage). 
The point of the presentation is that they don't work together well in 
some cases.  Apparently, each tool is thrown off by the weird (i.e., 
non-javac) code produced by the others.

>>
>>In general, you'd be surprised how many sources of bytecode there are 
>>besides javac, so you'll eventually suffer if you concentrate too much 
>>on handling just that kind of code.
> 
> 
> That depends entirely on what you are trying to do.
> 

You're right, of course.

-- 
"I say to you that the VCR is to the American film
producer and the American public as the Boston
strangler is to the woman home alone."
         -Jack Valenti, President, Motion Picture
          Association of America, Inc., before
          The House Subcommittee on Courts, Civil
          Liberties, and The Administration of
          Justice, August, 1982,
          http://cryptome.org/hrcw-hear.htm


Re: Constructor Instrumentation : super()

Posted by Erik Corry <er...@arbat.com>.
On Wed, Feb 18, 2004 at 02:59:24PM -0700, Andrew Huntwork wrote:
> Depending on what 
> kind of instrumentation you want to do, this is sufficient.  For 
> example, if you just want to know a complete call trace, you can insert 
> the bytecode equivalent of the following at every method entry and exit:
> 
> log("entering/leaving foo.bar()V");

Except that you can't do that right at entry of the constructor
(before the call to the superclass constructor).  Try it.  Or
look at the code in the Helloifier:

http://cvs.sourceforge.net/viewcvs.py/bcel/BCEL/helloify.java?view=markup

Look for "init".  The code is there for a reason, and it's not
sufficient.

> >>Second, you could do some pretty complicated stack and control flow 
> >>analysis.  Here's something that's legal in bytecode but not in java:
> >>
> >>if(...)
> >> super(foo);
> >>else
> >> super(bar);
> >
> >
> >Are you sure that's legal?  The VM spec says:
> >
> >    "If a constructor body does not begin with an explicit
> >    constructor invocation and the constructor being declared
> >    is not part of the primordial class Object, then the
> >    constructor body is implicitly assumed by the compiler to
> >    begin with a superclass constructor invocation "super();",
> >    an invocation of the constructor of the direct superclass
> >    that takes no arguments."
> >
> >Does you example begin with an explicit constructor invocation?
> >I don't think it does.  Is it allowed to call two different
> >constructors for the same class on an object?
> 
> As I say, not legal in Java (which your passage refers to), but totally 
> legal in bytecode.

My passage refers to the VM spec, so it's about byte code, not
about the Java language.

> The attached class has this <init>:
> 
> Method test()
>    0 iconst_0
>    1 ifeq 11
>    4 aload_0
>    5 invokespecial #10 <Method java.lang.Object()>
>    8 goto 15
>   11 aload_0
>   12 invokespecial #10 <Method java.lang.Object()>
>   15 return
> 
> it verifies just fine

OK.  I never would have guessed from the spec.

> >Does anyone do that?
> 
> [No concrete examples mentioned]
> 
> In general, you'd be surprised how many sources of bytecode there are 
> besides javac, so you'll eventually suffer if you concentrate too much 
> on handling just that kind of code.

That depends entirely on what you are trying to do.

-- 
Erik Corry         I'd be a Libertarian, if they weren't all a
erik@arbat.com     bunch of tax-dodging professional whiners.   - B. Breathed.

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


Re: Constructor Instrumentation : super()

Posted by Andrew Huntwork <as...@huntwork.net>.
I can't think of any javac output that will cause any problems with this 
approach.  So as far as I can see, Eric's is a pretty nice way to deal 
with all the normal inputs.

Nikhil C. Khedkar wrote:
> Hi Erik and Andrew,
> 	Finally able to get this thing fixed. Here's the
> approach I have followed (Just for everyone's
> information).
> 
> 1)Firstly detect that a method is constructor from its
> name "<init>".
> 2)Put a try catch block.
> 3)Take care to skip super() calls which should be the
> first line in the constructor. [Andrew won't agree
> with this. He has indeed provided me with some code,
> but I think my assumption is true for normal Sun javac
> compiler. Andrew please confirm]
> 4)Now the approach to find super() call and
> distinguish it from an explict new() call.
> Scan all the instructions in the constructor from 0
> onwards. Keep a counter initialized at 0. Increment
> the counter when you encounter a NEW instruction.
> Decrement it when you encounter a INVOKESPECIAL
> (that's how you create an object). When this counter
> becomes negative, you have encountered a super() call.
> When this counter becomes 0, its the new() call.
> [Thanks Eric]
> 
> That's all.
> 
> Thanks,
> 	Nikhil Khedkar
> 

-- 
"I say to you that the VCR is to the American film
producer and the American public as the Boston
strangler is to the woman home alone."
         -Jack Valenti, President, Motion Picture
          Association of America, Inc., before
          The House Subcommittee on Courts, Civil
          Liberties, and The Administration of
          Justice, August, 1982,
          http://cryptome.org/hrcw-hear.htm


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


Re: Constructor Instrumentation : super()

Posted by "Nikhil C. Khedkar" <ni...@yahoo.com>.
Hi Erik and Andrew,
	Finally able to get this thing fixed. Here's the
approach I have followed (Just for everyone's
information).

1)Firstly detect that a method is constructor from its
name "<init>".
2)Put a try catch block.
3)Take care to skip super() calls which should be the
first line in the constructor. [Andrew won't agree
with this. He has indeed provided me with some code,
but I think my assumption is true for normal Sun javac
compiler. Andrew please confirm]
4)Now the approach to find super() call and
distinguish it from an explict new() call.
Scan all the instructions in the constructor from 0
onwards. Keep a counter initialized at 0. Increment
the counter when you encounter a NEW instruction.
Decrement it when you encounter a INVOKESPECIAL
(that's how you create an object). When this counter
becomes negative, you have encountered a super() call.
When this counter becomes 0, its the new() call.
[Thanks Eric]

That's all.

Thanks,
	Nikhil Khedkar


Here's my problem statement if you haven't read it
previously:

Hi,
	I have a query regarding the instrumentation of the
constructor. I have read all the archived mail in this
regard, but none of them served useful. I have the
same requirement i.e. put a method call at each method
start and method end. Have already put a try catch for
that. Now the task is to skip super() call before I
put my method call in the constructor.
	
	I have a code that works for 99% of the cases. 
	
	for(int j = 1; j < ihs.length; j++)
	{
		if(ihs[j].getInstruction() instanceof INVOKESPECIAL)
		{
			il.append(ihs[j], instrumentedPatchList);
			break;
		}
	}
	
	It works for 
	
	1)public ABCD(XYZ obj)
	{
		super(obj);
	}
	
	Now a more complicated case
	
	2)public Tree(int type, MainPanel mainPanel)
	{
		super(new DefaultTreeModel(new RuleNode("Rules")));
		method1();
		method2();
	}
	
	The above code fails because the Special Instruction
is not at first position. Hence A refined approach
will be to get the first instruction handle of the
second line in the constructor (first instruction
handle for method1()). Now I scan all the instructions
of the first line (super(new DefaultTreeModel(new
RuleNode("Rules")))). If there is any INVOKESPECIAL in
this list I put my code at the end of first line. This
thing works fine.
	
	A bit more complex case
	
	3)private XYZHandler(EventHandler commandHandler)
	{
		super(
			ABCD.getInstance(),
			Helper.getInstance(),
			commandHandler,
			100);
		method1();
	}
	
	Now the above mentioned approach doesn't work and I
end up putting my method call before super() and get
VerifyError. Has anyone (especially the ones who have
posted those questions on constructor instrumentation
previously) been able to build a fullproof code?
	
Thanks,
	Nikhil Khedkar

__________________________________
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.
http://antispam.yahoo.com/tools

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


Re: Constructor Instrumentation : super()

Posted by "Nikhil C. Khedkar" <ni...@yahoo.com>.
Hi Erik and Andrew,
	Finally able to get this thing fixed. Here's the
approach I have followed (Just for everyone's
information).

1)Firstly detect that a method is constructor from its
name "<init>".
2)Put a try catch block.
3)Take care to skip super() calls which should be the
first line in the constructor. [Andrew won't agree
with this. He has indeed provided me with some code,
but I think my assumption is true for normal Sun javac
compiler. Andrew please confirm]
4)Now the approach to find super() call and
distinguish it from an explict new() call.
Scan all the instructions in the constructor from 0
onwards. Keep a counter initialized at 0. Increment
the counter when you encounter a NEW instruction.
Decrement it when you encounter a INVOKESPECIAL
(that's how you create an object). When this counter
becomes negative, you have encountered a super() call.
When this counter becomes 0, its the new() call.
[Thanks Eric]

That's all.

Thanks,
	Nikhil Khedkar


Here's my problem statement if you haven't read it
previously:

Hi,
	I have a query regarding the instrumentation of the
constructor. I have read all the archived mail in this
regard, but none of them served useful. I have the
same requirement i.e. put a method call at each method
start and method end. Have already put a try catch for
that. Now the task is to skip super() call before I
put my method call in the constructor.
	
	I have a code that works for 99% of the cases. 
	
	for(int j = 1; j < ihs.length; j++)
	{
		if(ihs[j].getInstruction() instanceof INVOKESPECIAL)
		{
			il.append(ihs[j], instrumentedPatchList);
			break;
		}
	}
	
	It works for 
	
	1)public ABCD(XYZ obj)
	{
		super(obj);
	}
	
	Now a more complicated case
	
	2)public Tree(int type, MainPanel mainPanel)
	{
		super(new DefaultTreeModel(new RuleNode("Rules")));
		method1();
		method2();
	}
	
	The above code fails because the Special Instruction
is not at first position. Hence A refined approach
will be to get the first instruction handle of the
second line in the constructor (first instruction
handle for method1()). Now I scan all the instructions
of the first line (super(new DefaultTreeModel(new
RuleNode("Rules")))). If there is any INVOKESPECIAL in
this list I put my code at the end of first line. This
thing works fine.
	
	A bit more complex case
	
	3)private XYZHandler(EventHandler commandHandler)
	{
		super(
			ABCD.getInstance(),
			Helper.getInstance(),
			commandHandler,
			100);
		method1();
	}
	
	Now the above mentioned approach doesn't work and I
end up putting my method call before super() and get
VerifyError. Has anyone (especially the ones who have
posted those questions on constructor instrumentation
previously) been able to build a fullproof code?
	
Thanks,
	Nikhil Khedkar

__________________________________
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.
http://antispam.yahoo.com/tools

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


Re: Constructor Instrumentation : super()

Posted by Andrew Huntwork <as...@huntwork.net>.
Erik Corry wrote:
> On Wed, Feb 18, 2004 at 10:28:52AM -0700, Andrew Huntwork wrote:
> 
>>There are a couple things you could do, one of which may be easy.
>>
>>First, you could make the instrumentation method you're calling static. 
>> I assume the verifier error you're getting is that you're trying to do 
>>a virtual method call on an uninitialized object.  Calling a static 
>>method  won't call a method on an object, so you'll be fine.
> 
> 
> No, that doesn't work either.  It's a different problem to the one
> you think.  See VM spec section 4.9.4:
> 
>    "a special type is created and pushed on the verifier's
>     model of the operand stack as the result of the Java virtual
>     machine instruction new. The special type indicates the
>     instruction by which the class instance was created and
>     the type of the uninitialized class instance created"
> 
> The only thing you can do with that object is call the <init>
> (contstructor) method.  You can't pass it as a parameter to a
> profiling routine.
> 
> It's quite an irritating restriction.

Right, you won't be able to make 'this' a parameter to the static 
function, but you can still call the static function.  Depending on what 
kind of instrumentation you want to do, this is sufficient.  For 
example, if you just want to know a complete call trace, you can insert 
the bytecode equivalent of the following at every method entry and exit:

log("entering/leaving foo.bar()V");

> 
> 
>>Second, you could do some pretty complicated stack and control flow 
>>analysis.  Here's something that's legal in bytecode but not in java:
>>
>>if(...)
>>  super(foo);
>>else
>>  super(bar);
> 
> 
> Are you sure that's legal?  The VM spec says:
> 
>     "If a constructor body does not begin with an explicit
>     constructor invocation and the constructor being declared
>     is not part of the primordial class Object, then the
>     constructor body is implicitly assumed by the compiler to
>     begin with a superclass constructor invocation "super();",
>     an invocation of the constructor of the direct superclass
>     that takes no arguments."
> 
> Does you example begin with an explicit constructor invocation?
> I don't think it does.  Is it allowed to call two different
> constructors for the same class on an object?

As I say, not legal in Java (which your passage refers to), but totally 
legal in bytecode.  The attached class has this <init>:

Method test()
    0 iconst_0
    1 ifeq 11
    4 aload_0
    5 invokespecial #10 <Method java.lang.Object()>
    8 goto 15
   11 aload_0
   12 invokespecial #10 <Method java.lang.Object()>
   15 return

it verifies just fine

> 
> 
>>and here's something else that's legal in bytecode
>>
>>void <init>(Object foo) {
>>aload_0
>>aload_1
>>astore_0
>>dup
>>invokespecial <init>()V
>>astore_1
>>return
>>}
> 
> 
> Does anyone do that?
> 

I don't know what kind of optimizations BLOAT,soot,dasho, or any of the 
other bytecode optimizers do, but some kind of register allocation 
optimization could do something similar under some circumstances.  Also, 
there are several bytecode obfuscators out there, including sandmark. 
If some kind of reverse engineering tool depended on lv 0 always being 
'this', i'm sure several groups would generate this kind of code just to 
screw that tool up.

In general, you'd be surprised how many sources of bytecode there are 
besides javac, so you'll eventually suffer if you concentrate too much 
on handling just that kind of code.

-- 
"I say to you that the VCR is to the American film
producer and the American public as the Boston
strangler is to the woman home alone."
         -Jack Valenti, President, Motion Picture
          Association of America, Inc., before
          The House Subcommittee on Courts, Civil
          Liberties, and The Administration of
          Justice, August, 1982,
          http://cryptome.org/hrcw-hear.htm


Re: Constructor Instrumentation : super()

Posted by Erik Corry <er...@arbat.com>.
On Wed, Feb 18, 2004 at 10:28:52AM -0700, Andrew Huntwork wrote:
> There are a couple things you could do, one of which may be easy.
> 
> First, you could make the instrumentation method you're calling static. 
>  I assume the verifier error you're getting is that you're trying to do 
> a virtual method call on an uninitialized object.  Calling a static 
> method  won't call a method on an object, so you'll be fine.

No, that doesn't work either.  It's a different problem to the one
you think.  See VM spec section 4.9.4:

   "a special type is created and pushed on the verifier's
    model of the operand stack as the result of the Java virtual
    machine instruction new. The special type indicates the
    instruction by which the class instance was created and
    the type of the uninitialized class instance created"

The only thing you can do with that object is call the <init>
(contstructor) method.  You can't pass it as a parameter to a
profiling routine.

It's quite an irritating restriction.

> Second, you could do some pretty complicated stack and control flow 
> analysis.  Here's something that's legal in bytecode but not in java:
> 
> if(...)
>   super(foo);
> else
>   super(bar);

Are you sure that's legal?  The VM spec says:

    "If a constructor body does not begin with an explicit
    constructor invocation and the constructor being declared
    is not part of the primordial class Object, then the
    constructor body is implicitly assumed by the compiler to
    begin with a superclass constructor invocation "super();",
    an invocation of the constructor of the direct superclass
    that takes no arguments."

Does you example begin with an explicit constructor invocation?
I don't think it does.  Is it allowed to call two different
constructors for the same class on an object?

> and here's something else that's legal in bytecode
> 
> void <init>(Object foo) {
> aload_0
> aload_1
> astore_0
> dup
> invokespecial <init>()V
> astore_1
> return
> }

Does anyone do that?

-- 
Erik Corry         I'd be a Libertarian, if they weren't all a
erik@arbat.com     bunch of tax-dodging professional whiners.   - B. Breathed.

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


Re: Constructor Instrumentation : super()

Posted by Andrew Huntwork <as...@huntwork.net>.
There are a couple things you could do, one of which may be easy.

First, you could make the instrumentation method you're calling static. 
  I assume the verifier error you're getting is that you're trying to do 
a virtual method call on an uninitialized object.  Calling a static 
method  won't call a method on an object, so you'll be fine.

Second, you could do some pretty complicated stack and control flow 
analysis.  Here's something that's legal in bytecode but not in java:

if(...)
   super(foo);
else
   super(bar);

and here's something else that's legal in bytecode

void <init>(Object foo) {
aload_0
aload_1
astore_0
dup
invokespecial <init>()V
astore_1
return
}

So you'll want to insert your instrumentation after both calls to 
super(), or something like that.  One way to find all the super()'s that 
initialize this is to have a mechanism to determine what's on the stack 
before every instruction.  Then, if the thing on the top of the stack at 
a super() call (or 1 down from the top in a super(foo) call, etc) is the 
same thing that was in local 0 at the beginning of the method (not 
necessarily now, see second example), then this super() initializes 
this.  I don't think there is an easier way to be 100% correct. 
Fortunately for me (since I have to do this analysis in several places, 
including once where i'm doing something similar to what you're doing -- 
tracing execution paths), sandmark (www.cs.arizona.edu/sandmark/) has a 
stack simulator implementation that does just this kind of analysis.

BTW, for some reason i'm not getting Erik Corry's list posts that i see 
in the archive, so I'll just note here that my first code example above 
is an illustration of why the counter he describes won't work for 
general java bytecode.  It seems like it might work fine for javac 
output though.

Also, the verification of <init> and object initialization is described 
in JVM spec section 4.9.4.

Nikhil C. Khedkar wrote:
> Hi,
> 	I have a query regarding the instrumentation of the
> constructor. I have read all the archived mail in this
> regard, but none of them served useful. I have the
> same requirement i.e. put a method call at each method
> start and method end. Have already put a try catch for
> that. Now the task is to skip super() call before I
> put my method call in the constructor.
> 	
> 	I have a code that works for 99% of the cases. 
> 	
> 	for(int j = 1; j < ihs.length; j++)
> 	{
> 		if(ihs[j].getInstruction() instanceof INVOKESPECIAL)
> 		{
> 			il.append(ihs[j], instrumentedPatchList);
> 			break;
> 		}
> 	}
> 	
> 	It works for 
> 	
> 	1)public ABCD(XYZ obj)
> 	{
> 		super(obj);
> 	}
> 	
> 	Now a more complicated case
> 	
> 	2)public RuleTree(int type, AppCodeAnalyzerMainPanel
> mainPanel)
> 	{
> 		super(new DefaultTreeModel(new RuleNode("Rules")));
> 		method1();
> 		method2();
> 	}
> 	
> 	The above code fails because the Special Instruction
> is not at first position. Hence A refined approach
> will be to get the first instruction handle of the
> second line in the constructor (first instruction
> handle for method1()). Now I scan all the instructions
> of the first line (super(new DefaultTreeModel(new
> RuleNode("Rules")))). If there is any INVOKESPECIAL in
> this list I put my code at the end of first line. This
> thing works fine.
> 	
> 	A bit more complex case
> 	
> 	3)private XYZHandler(EventHandler commandHandler)
> 	{
> 		super(
> 			ABCD.getInstance(),
> 			Helper.getInstance(),
> 			commandHandler,
> 			100);
> 		method1();
> 	}
> 	
> 	Now the above mentioned approach doesn't work and I
> end up putting my method call before super() and get
> VerifyError. Has anyone (especially the ones who have
> posted those questions on constructor instrumentation
> previously) been able to build a fullproof code?
> 	
> Thanks,
> 	Nikhil Khedkar
> 
> __________________________________
> Do you Yahoo!?
> Yahoo! Mail SpamGuard - Read only the mail you want.
> http://antispam.yahoo.com/tools
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: bcel-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: bcel-dev-help@jakarta.apache.org
> 

-- 
"I say to you that the VCR is to the American film
producer and the American public as the Boston
strangler is to the woman home alone."
         -Jack Valenti, President, Motion Picture
          Association of America, Inc., before
          The House Subcommittee on Courts, Civil
          Liberties, and The Administration of
          Justice, August, 1982,
          http://cryptome.org/hrcw-hear.htm


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


Re: Constructor Instrumentation : super()

Posted by Erik Corry <er...@arbat.com>.
On Wed, Feb 18, 2004 at 04:34:02AM -0800, Nikhil C. Khedkar wrote:
> I think I am nearing the solution. Yes I can check if
> teh INVOKESPECIAL is of some super class. Just have
> one more problem now. What if I instantiate the super
> class in the constructor by a new statement? How can I
> distinguish super() from new(). Both the INVOKESPECIAL
> are exactly the same. The only hope now is the DUP
> instruction. My assumption is DUP is inserted whenever
> new() is used in the code? Am I right?

I think you are wrong.  If the statement is:

    new Myclass();

Doesn't need to keep the reference to the new object around
so why should it do a dup?

Why look for the dup instruction when you can look for the
'new' instruction?

> If the answer
> is yes, then I can distinguish super() from new().

I guess if you want a 100% solution you have to trace
where the objects come from so that you can see whether
the object that you are calling init on is the first
parameter or whether it comes from a call to new.

Alternatively (not 100% but probably works in practice):

Have a counter that starts at 0.  Scan the instructions
linearly.  When you hit a new instruction increment it.  When
you hit a call to <init> decrement it.  If it goes negative
then you have found the correct call to the superclass of
the constructor.  If it never goes negative there is no call.
Do some sanity checking to make sure the constructor call
you have found has the right type.

I wonder what the verifier does.

-- 
Erik Corry         I'd be a Libertarian, if they weren't all a
erik@arbat.com     bunch of tax-dodging professional whiners.   - B. Breathed.

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


Re: Constructor Instrumentation : super()

Posted by "Nikhil C. Khedkar" <ni...@yahoo.com>.
I think I am nearing the solution. Yes I can check if
teh INVOKESPECIAL is of some super class. Just have
one more problem now. What if I instantiate the super
class in the constructor by a new statement? How can I
distinguish super() from new(). Both the INVOKESPECIAL
are exactly the same. The only hope now is the DUP
instruction. My assumption is DUP is inserted whenever
new() is used in the code? Am I right? If the answer
is yes, then I can distinguish super() from new().

- Nikhil

--- Erik Corry <er...@arbat.com> wrote:
> On Wed, Feb 18, 2004 at 02:14:20AM -0800, Nikhil C.
> Khedkar wrote:
> > Well no peoblem with detecting the constructor.
> The
> > approach you have mentioned is not full proof. In
> my
> > constructor I have the following code, few lines
> down
> > the line
> > 
> > 		if (!(type == MAINUI || type == PROJECTWIZARD))
> > 		{
> > 			throw new RuntimeException("Invalid type");
> > 		}
> > 
> > Even this chap has INVOKESPECIAL and I end up
> skipping
> > some of the lines and in fact this line also, if I
> use
> > your approach, which I had already tried.
> 
> If you do "getClassName" in the INVOKESPECIAL
> instruction does
> that tell you the class that we are calling?  Or
> should we
> be using a different function.   The documentation
> is a little
> sparse...
> 
>
http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/generic/FieldOrMethod.html#getClassType(org.apache.bcel.generic.ConstantPoolGen)
> 
> (linked from
>
http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/generic/INVOKESPECIAL.html
> )
> 
> -- 
> Erik Corry         I'd be a Libertarian, if they
> weren't all a
> erik@arbat.com     bunch of tax-dodging professional
> whiners.   - B. Breathed.
> 
>
---------------------------------------------------------------------
> To unsubscribe, e-mail:
> bcel-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail:
> bcel-user-help@jakarta.apache.org
> 


__________________________________
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.
http://antispam.yahoo.com/tools

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


Re: Constructor Instrumentation : super()

Posted by "Nikhil C. Khedkar" <ni...@yahoo.com>.
I think I am nearing the solution. Yes I can check if
teh INVOKESPECIAL is of some super class. Just have
one more problem now. What if I instantiate the super
class in the constructor by a new statement? How can I
distinguish super() from new(). Both the INVOKESPECIAL
are exactly the same. The only hope now is the DUP
instruction. My assumption is DUP is inserted whenever
new() is used in the code? Am I right? If the answer
is yes, then I can distinguish super() from new().

- Nikhil

--- Erik Corry <er...@arbat.com> wrote:
> On Wed, Feb 18, 2004 at 02:14:20AM -0800, Nikhil C.
> Khedkar wrote:
> > Well no peoblem with detecting the constructor.
> The
> > approach you have mentioned is not full proof. In
> my
> > constructor I have the following code, few lines
> down
> > the line
> > 
> > 		if (!(type == MAINUI || type == PROJECTWIZARD))
> > 		{
> > 			throw new RuntimeException("Invalid type");
> > 		}
> > 
> > Even this chap has INVOKESPECIAL and I end up
> skipping
> > some of the lines and in fact this line also, if I
> use
> > your approach, which I had already tried.
> 
> If you do "getClassName" in the INVOKESPECIAL
> instruction does
> that tell you the class that we are calling?  Or
> should we
> be using a different function.   The documentation
> is a little
> sparse...
> 
>
http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/generic/FieldOrMethod.html#getClassType(org.apache.bcel.generic.ConstantPoolGen)
> 
> (linked from
>
http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/generic/INVOKESPECIAL.html
> )
> 
> -- 
> Erik Corry         I'd be a Libertarian, if they
> weren't all a
> erik@arbat.com     bunch of tax-dodging professional
> whiners.   - B. Breathed.
> 
>
---------------------------------------------------------------------
> To unsubscribe, e-mail:
> bcel-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail:
> bcel-user-help@jakarta.apache.org
> 


__________________________________
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.
http://antispam.yahoo.com/tools

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


Re: Constructor Instrumentation : super()

Posted by Erik Corry <er...@arbat.com>.
On Wed, Feb 18, 2004 at 02:14:20AM -0800, Nikhil C. Khedkar wrote:
> Well no peoblem with detecting the constructor. The
> approach you have mentioned is not full proof. In my
> constructor I have the following code, few lines down
> the line
> 
> 		if (!(type == MAINUI || type == PROJECTWIZARD))
> 		{
> 			throw new RuntimeException("Invalid type");
> 		}
> 
> Even this chap has INVOKESPECIAL and I end up skipping
> some of the lines and in fact this line also, if I use
> your approach, which I had already tried.

If you do "getClassName" in the INVOKESPECIAL instruction does
that tell you the class that we are calling?  Or should we
be using a different function.   The documentation is a little
sparse...

http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/generic/FieldOrMethod.html#getClassType(org.apache.bcel.generic.ConstantPoolGen)

(linked from http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/generic/INVOKESPECIAL.html )

-- 
Erik Corry         I'd be a Libertarian, if they weren't all a
erik@arbat.com     bunch of tax-dodging professional whiners.   - B. Breathed.

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


Re: Constructor Instrumentation : super()

Posted by "Nikhil C. Khedkar" <ni...@yahoo.com>.
Well no peoblem with detecting the constructor. The
approach you have mentioned is not full proof. In my
constructor I have the following code, few lines down
the line

		if (!(type == MAINUI || type == PROJECTWIZARD))
		{
			throw new RuntimeException("Invalid type");
		}

Even this chap has INVOKESPECIAL and I end up skipping
some of the lines and in fact this line also, if I use
your approach, which I had already tried.

<bc...@jakarta.apache.org>
--- Erik Corry <er...@arbat.com> wrote:
> On Wed, Feb 18, 2004 at 01:58:04AM -0800, Nikhil C.
> Khedkar wrote:
> > 	Now the above mentioned approach doesn't work and
> I
> > end up putting my method call before super() and
> get
> > VerifyError.
> 
> Since the constructor has a special name (<init>)
> you
> can know that you are dealing with a constructor.
> If so, scan the whole method for a call to the
> superclass constructor (INVOKESPECIAL to a method
> called
> <init>).  If you don't find it (it seems legal
> according to
>
http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#16411
> ) then you can put your instrumenting call at the
> start,
> otherwise you put the call after the INVOKESPECIAL
> call.
> 
> I haven't tried it, so I'd be interested in whether
> it works.
> I'm going to be needing it realy soon for my own
> project.
> 
> -- 
> Erik Corry         I'd be a Libertarian, if they
> weren't all a
> erik@arbat.com     bunch of tax-dodging professional
> whiners.   - B. Breathed.
> 
>
---------------------------------------------------------------------
> To unsubscribe, e-mail:
> bcel-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail:
> bcel-user-help@jakarta.apache.org
> 


__________________________________
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.
http://antispam.yahoo.com/tools

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


Re: Constructor Instrumentation : super()

Posted by "Nikhil C. Khedkar" <ni...@yahoo.com>.
Well no peoblem with detecting the constructor. The
approach you have mentioned is not full proof. In my
constructor I have the following code, few lines down
the line

		if (!(type == MAINUI || type == PROJECTWIZARD))
		{
			throw new RuntimeException("Invalid type");
		}

Even this chap has INVOKESPECIAL and I end up skipping
some of the lines and in fact this line also, if I use
your approach, which I had already tried.

<bc...@jakarta.apache.org>
--- Erik Corry <er...@arbat.com> wrote:
> On Wed, Feb 18, 2004 at 01:58:04AM -0800, Nikhil C.
> Khedkar wrote:
> > 	Now the above mentioned approach doesn't work and
> I
> > end up putting my method call before super() and
> get
> > VerifyError.
> 
> Since the constructor has a special name (<init>)
> you
> can know that you are dealing with a constructor.
> If so, scan the whole method for a call to the
> superclass constructor (INVOKESPECIAL to a method
> called
> <init>).  If you don't find it (it seems legal
> according to
>
http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#16411
> ) then you can put your instrumenting call at the
> start,
> otherwise you put the call after the INVOKESPECIAL
> call.
> 
> I haven't tried it, so I'd be interested in whether
> it works.
> I'm going to be needing it realy soon for my own
> project.
> 
> -- 
> Erik Corry         I'd be a Libertarian, if they
> weren't all a
> erik@arbat.com     bunch of tax-dodging professional
> whiners.   - B. Breathed.
> 
>
---------------------------------------------------------------------
> To unsubscribe, e-mail:
> bcel-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail:
> bcel-user-help@jakarta.apache.org
> 


__________________________________
Do you Yahoo!?
Yahoo! Mail SpamGuard - Read only the mail you want.
http://antispam.yahoo.com/tools

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


Re: Constructor Instrumentation : super()

Posted by Erik Corry <er...@arbat.com>.
On Wed, Feb 18, 2004 at 01:58:04AM -0800, Nikhil C. Khedkar wrote:
> 	Now the above mentioned approach doesn't work and I
> end up putting my method call before super() and get
> VerifyError.

Since the constructor has a special name (<init>) you
can know that you are dealing with a constructor.
If so, scan the whole method for a call to the
superclass constructor (INVOKESPECIAL to a method called
<init>).  If you don't find it (it seems legal according to
http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#16411
) then you can put your instrumenting call at the start,
otherwise you put the call after the INVOKESPECIAL call.

I haven't tried it, so I'd be interested in whether it works.
I'm going to be needing it realy soon for my own project.

-- 
Erik Corry         I'd be a Libertarian, if they weren't all a
erik@arbat.com     bunch of tax-dodging professional whiners.   - B. Breathed.

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