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/16 22:11:02 UTC

RE: JavaClassFileOutputException: Stack underflow - FIXED

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