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 Johan Kumps <jo...@pandora.be> on 2004/07/15 13:25:43 UTC

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,

Johan,



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


RE: JavaClassFileOutputException: Stack underflow

Posted by Johan Kumps <jo...@pandora.be>.
Hi,

Thanks for replying. The mg variable indead point to a constructor(<init>).
How can I fix my problem?

Kind regards,

-----Oorspronkelijk bericht-----
Van: Dick Eimers [mailto:dweimers@cs.uu.nl]
Verzonden: donderdag 15 juli 2004 15:10
Aan: BCEL Users List
Onderwerp: 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..


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



---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.713 / Virus Database: 469 - Release Date: 30/06/2004

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.713 / Virus Database: 469 - Release Date: 30/06/2004


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


Re: JavaClassFileOutputException: Stack underflow

Posted by Dick Eimers <dw...@cs.uu.nl>.
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.. 


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


RE: JavaClassFileOutputException: Stack underflow - FIXED

Posted by Johan Kumps <jo...@pandora.be>.
Hi all,

I fixed my problem.

This is my code transforming an existing constructor :

InstructionList originalIl = mg.getInstructionList();
InstructionHandle instructionHandle[] = originalIl.getInstructionHandles();
            
InstructionList newIl = new InstructionList();                                            
newIl.append(factory.createInvoke("MySingleton", "getInstance", new ObjectType("MySingleton"), Type.NO_ARGS, Constants.INVOKESTATIC));
newIl.append(InstructionFactory.createLoad(Type.OBJECT, 0));
newIl.append(factory.createInvoke("java.lang.Object", "getClass", new ObjectType("java.lang.Class"), Type.NO_ARGS, Constants.INVOKEVIRTUAL));
newIl.append(factory.createInvoke("java.lang.Class", "getName", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
newIl.append(InstructionConstants.ACONST_NULL);
newIl.append(factory.createInvoke("MySingleton", "myMethod", Type.VOID, new Type[] { Type.STRING, new ObjectType("MyObject") }, Constants.INVOKEVIRTUAL));
            
// First let the super or other constructor be called!!!!!
for (int i = 1; i < instructionHandle.length; i++){
    if (instructionHandle[i].getInstruction() instanceof INVOKESPECIAL){
        originalIl.append(instructionHandle[i], newIl);
        break;
    }
}

The important part is the for loop. Looping through the original instruction list until all constructors are called. Afterwards the instructions of the newIL variable containing the new code are appended.

This is because the JVM spec states all constructor call's should be done before other statements are executed in a constructor.

I hope my solution can help others. If you know a better solution please let us know.

Kind regards,

-----Oorspronkelijk bericht-----
Van: Johan Kumps [mailto:johan.kumps@pandora.be]
Verzonden: donderdag 15 juli 2004 13:26
Aan: bcel-user@jakarta.apache.org
Onderwerp: 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,

Johan,




---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.713 / Virus Database: 469 - Release Date: 30/06/2004
 

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.713 / Virus Database: 469 - Release Date: 30/06/2004
 


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