Eric Chow | 1 Jul 2004 09:49

Urgent , BCEL beginner questions ???

Hi,

I am going to use BCEL to do some education project.
But I have so many problems and questions if I should use BCEL or other
library.

1. retrieve all the variable names and its corresponding values (global
variables, and local variables) ?
2. can I add a method with some source expression ??
    for example,

    clazzGen.addMethod(" int a = 10; System.out.println(a); "); // something
like this, Javassist provides this ....

3. can I insert a statement into a specific line within a method?
     for example,

     public void init() {
        int a = 10;
                    // <<<<<<< insert a statement here :    a = a * a;
        System.out.println(a);
     }

4. can I modify a specific statement ?
     for example,

     public void init(int x) {
        return x;     //<<<<<<<  modify it to:    return (x * 2);
     }

(Continue reading)

spamart | 11 Jul 2004 02:45
Picon
Favicon

accessing local variables

Hi ,

Is there a way to access local variables declared in a function in another function during run time.

Say for example I have the following program

public class abc{

public static void f()

{

 int x=10;

 .....

}

public static int g()

{

 int y=4;

  return x+y;

}

public static void main(String args[])

(Continue reading)

Dick Eimers | 12 Jul 2004 09:44
Picon

Re: accessing local variables


> Is there a way to access local variables declared in a function in another function during run time.

No this is not allowed by spec.

-Dick
Andrew Huntwork | 12 Jul 2004 16:32

Re: accessing local variables

Not only not allowed by the spec, but it doesn't necessarily even make 
any sense as stated.  If a function has never been invoked, what do you 
want the values of its variables to be?  Some languages have nested 
functions and i think usually nested functions a) can only be called 
from their outer function; and b) have access to the most recent 
invocation of the enclosing function.  Something like this:

function a() {
   function b() {
     return c;
   }
   if(bar())
     a();
   int c = foo();
   int d = b();
}

a recurses, but you usually expect that b will access c in the most 
recent invocation.

I think it would be somewhat painful but definitely possible to 
implement nested functions using bcel to copy local variable values into 
global vars before invoking the nested function.  or something like 
that.  but that's certainly not the exact question asked.

Dick Eimers wrote:
>> Is there a way to access local variables declared in a function in
>> another function during run time.
> 
> 
(Continue reading)

spamart | 12 Jul 2004 22:32
Picon
Favicon

Re: accessing local variables

Hi Andrew,
Thank you for your mail. Actually I wanted to implement nested functions. Say if I have the following declaration.

function f(){
 var x;
  function g()
  {
   var y
   return (x + y );
  }
  g();
}

print( f() );

I translate the same program into
class abc{

publc static void global()
{
  print( f() );

}
public static void f()
{
 var x;
 f$g();
}

public static int f$g()
(Continue reading)

Andrew Huntwork | 12 Jul 2004 22:59

Re: accessing local variables

uh, yeah, i did mean fields.  sorry, i don't know what i was thinking.

spamart <at> uark.edu wrote:

> Hi Andrew,
> Thank you for your mail. Actually I wanted to implement nested functions. Say if I have the following declaration.
> 
> function f(){
>  var x;
>   function g()
>   {
>    var y
>    return (x + y );
>   }
>   g();
> }
> 
> print( f() );
> 
> I translate the same program into
> class abc{
> 
> publc static void global()
> {
>   print( f() );
> 
> }
> public static void f()
> {
>  var x;
(Continue reading)

Dick Eimers | 14 Jul 2004 17:55
Picon

Relying on local variable slot 0

*** Retry: If this post reaches you twice, I apologize ***

This problem was brought to our attention by Toby Reyelts in October
2002, but was not really examined as much as I'd like :)

Many rewriting of existing methods rely on the *this* reference to be
in slot 0. When a method is invoked a new stack frame is created by
the virtual machine where the object reference to the object on which
the method is invoked, i.e. in Java programming language is referred to
as *this*, is placed in the first local variable slot indexed by 0. 

The object initialization method (<init>) is special, because slot 0
contains the uninitialized *this*, as explained in the VM Section
4.9.4 on how code is verified:

"When doing dataflow analysis on instance methods, the verifier
initializes local variable 0 to contain an object of the current
class, or, for instance initialization methods, local variable 0
contains a special type indicating an uninitialized object. After an
appropriate instance initialization method is invoked (from the
current class or the current superclass) on this object, all
occurrences of this special type on the verifier's model of the
operand stack and in the local variable array are replaced by the
current class type. The verifier rejects code that uses the new object
before it has been initialized or that initializes the object more
than once. In addition, it ensures that every normal return of the
method has invoked an instance initialization method either in the
class of this method or in the direct superclass."

Reyelts said he'd seen bytecode which overwrites slot 0, so the "this"
(Continue reading)

Dick Eimers | 14 Jul 2004 13:07
Picon

Relying on local variable slot 0

This problem was brought to our attention by Toby Reyelts in October
2002, but was not really examined as much as I'd like :)

Many rewriting of existing methods rely on the *this* reference to be
in slot 0. When a method is invoked a new stack frame is created by
the virtual machine where the object reference to the object on which
the method is invoked, i.e. in Java programming language is referred to
as *this*, is placed in the first local variable slot indexed by 0. 

The object initialization method (<init>) is special, because slot 0
contains the uninitialized *this*, as explained in the VM Section
4.9.4 on how code is verified:

"When doing dataflow analysis on instance methods, the verifier
initializes local variable 0 to contain an object of the current
class, or, for instance initialization methods, local variable 0
contains a special type indicating an uninitialized object. After an
appropriate instance initialization method is invoked (from the
current class or the current superclass) on this object, all
occurrences of this special type on the verifier's model of the
operand stack and in the local variable array are replaced by the
current class type. The verifier rejects code that uses the new object
before it has been initialized or that initializes the object more
than once. In addition, it ensures that every normal return of the
method has invoked an instance initialization method either in the
class of this method or in the direct superclass."

Reyelts said he'd seen bytecode which overwrites slot 0, so the "this"
reference that's placed there when the method begins execution is
lost, and thus cannot be relied on!  He proposed a solutions where the
(Continue reading)

Johan Kumps | 15 Jul 2004 13:25
Picon

JavaClassFileOutputException: Stack underflow

Hi all,

I'm trying to insert some code in the constructor of certain classes. The code should be getting the current
singleton instance of a class 'MySingleton' and call a method 'myMethod' on this instance. My code is as
follows :

InstructionList il = mg.getInstructionList();         
il.insert(factory.createInvoke("MySingleTon", "getInstance", new ObjectType("MySingleton"),
Type.NO_ARGS, Constants.INVOKESTATIC));
il.insert(InstructionFactory.createLoad(Type.OBJECT, 0));
il.insert(factory.createInvoke("java.lang.Object", "getClass", new
ObjectType("java.lang.Class"), Type.NO_ARGS, Constants.INVOKEVIRTUAL));
il.insert(factory.createInvoke("java.lang.Class", "getName", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
il.insert(InstructionConstants.ACONST_NULL);
il.insert(factory.createInvoke("MySingleton", "myMethod", Type.VOID, new Type[] { Type.STRING,
new ObjectType("MyObject") }, Constants.INVOKEVIRTUAL));

mg.setInstructionList(il);
mg.setMaxStack();

When I decompile the patched class the method to which I inserted the code has dissapeared and the following
line is added in place :

// JavaClassFileOutputException: Stack underflow

Does anybody has an idea of what I'm doing wrong? Can you provide me a code sample doing something like I want
to achieve?

Kind regards,

(Continue reading)

Dick Eimers | 15 Jul 2004 15:09
Picon

Re: JavaClassFileOutputException: Stack underflow

Instrumenting object initialization methods, methods with the special
name <init> (constructors are a Java programming language concept)
require caution. Various discussions covered the topic, but it comes
down to that all object initializers should invoke another object
initializer either in the current class or the superclass (chaining). If
your code does not rely on a reference to the object that is being
initialized (the Java programming language *this*) then it is safe to
insert the code at the beginning of the instructionlist.. 

> I'm trying to insert some code in the constructor of certain classes. The code should be getting the
current singleton instance of a class 'MySingleton' and call a method 'myMethod' on this instance. My
code is as follows :
> 
> InstructionList il = mg.getInstructionList();         
> il.insert(factory.createInvoke("MySingleTon", "getInstance", new ObjectType("MySingleton"),
Type.NO_ARGS, Constants.INVOKESTATIC));
> il.insert(InstructionFactory.createLoad(Type.OBJECT, 0));
> il.insert(factory.createInvoke("java.lang.Object", "getClass", new
ObjectType("java.lang.Class"), Type.NO_ARGS, Constants.INVOKEVIRTUAL));
> il.insert(factory.createInvoke("java.lang.Class", "getName", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
> il.insert(InstructionConstants.ACONST_NULL);
> il.insert(factory.createInvoke("MySingleton", "myMethod", Type.VOID, new Type[] { Type.STRING,
new ObjectType("MyObject") }, Constants.INVOKEVIRTUAL));
>             
> mg.setInstructionList(il);
> mg.setMaxStack();

If mg is a <init> then you're about to have a conflict with the
verifier.. 
(Continue reading)


Gmane