Re: Problems with Try/Catch Blocks
Vincent Marquez <[email protected]>
| Newsgroups | gmane.comp.jakarta.bcel.user |
|---|---|
| Message-ID | <[email protected]> |
Andrew, I changed the 'insert/delete' to a replace, and it didn't seem
to help the 'inconsistant stack height' problem. Heres my new method i
used, and I've included before and after bytecode. If another format
would be more helpful, just let me know. Thanks for taking a look at my
problem. Hopefully i'm just missing something and not doing something
that shouldn't be done.
--Vince
============= BEFORE ===============================
method name = public void <init>()
aload_0
invokespecial java/lang/Object/<init>()V
return
method name = public static java.util.ArrayList getArrList()
new java/util/ArrayList
dup
invokespecial java/util/ArrayList/<init>()V
areturn
method name = public static void main(String[] arg0)
getstatic java.lang.System.out Ljava/io/PrintStream;
ldc "test"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
new java/util/ArrayList
dup
invokespecial java/util/ArrayList/<init>()V
astore_1
goto -> 20
astore_1
getstatic java.lang.System.out Ljava/io/PrintStream;
ldc "test test test"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
=======================================================
=============== AFTER ==================================
method name = public void <init>()
aload_0
invokespecial java/lang/Object/<init>()V
return
method name = public static java.util.ArrayList getArrList()
new java/util/ArrayList
dup
invokestatic java/util/ArrayList/getArrList()Ljava/util/ArrayList;
LoadClassType = java.util.ArrayList
areturn
method name = public static void main(String[] arg0)
getstatic java.lang.System.out Ljava/io/PrintStream;
ldc "test"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
new java/util/ArrayList
dup
invokestatic java/util/ArrayList/getArrList()Ljava/util/ArrayList;
LoadClassType = java.util.ArrayList
astore_1
goto -> 20
astore_1
getstatic java.lang.System.out Ljava/io/PrintStream;
ldc "test test test"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
====================================================================
================= Method used to alter the class
==============================
protected void replaceConstructor( ClassGen cg, String
original_class, String new_class, String static_method_name ) {
boolean refresh = false;
ConstantPoolGen cp_gen = cg.getConstantPool();
ConstantPool cp = cp_gen.getConstantPool();
InstructionFactory factory = new InstructionFactory( cg , cp_gen );
Method [] methods = cg.getMethods();
for ( int x=0; x<methods.length; x++ ) {
refresh = false;
MethodGen method_gen = new MethodGen( methods[x],
cg.getJavaClass().getClassName(), cp_gen );
Iterator i = method_gen.getInstructionList().iterator();
while ( i.hasNext() ) {
InstructionHandle handle = ( InstructionHandle )i.next();
if ( handle.getInstruction() instanceof INVOKESPECIAL &&
( ( INVOKESPECIAL )handle.getInstruction() ).getClassName( cp_gen
).equals( original_class ) && ( ( INVOKESPECIAL )handle.getInstruction()
).getMethodName( cp_gen ).equals( "<init>" ) ) {
try {
INVOKESPECIAL invk = ( INVOKESPECIAL
)handle.getInstruction();
handle.setInstruction( factory.createInvoke(
new_class,
static_method_name,
new ObjectType( original_class ),
invk.getArgumentTypes( cp_gen ),
Constants.INVOKESTATIC ) );
refresh = true;
//} catch (
org.apache.bcel.generic.TargetLostException e ) {
} catch ( Exception e ) {
Log.write( "ERROR", e.toString() );
}
}
}
if ( refresh ) {
method_gen.stripAttributes( false );
method_gen.setMaxStack();
method_gen.setMaxLocals();
cg.replaceMethod( methods[x],
method_gen.getMethod() );
}
}
}
=====================================================================================
Andrew Huntwork wrote:
> Posting disassembly for a simple test before and after modification
> would be very helpful. There are a couple obvious problems with the
> method you've presented: it doesn't replace the NEW instruction that
> matches the invokespecial; and it ignores the TargetLostException that
> will certainly occur in some code. The second problem is easily
> solvable by using InstructionHandle.setInstruction instead of
> InstructionList.insert/delete. The first is probably an artifact of
> not seeing all your code.
>
> Vincent Marquez wrote:
>
>>
>> My problem is, while i'm modifying a method, if the method i'm
>> modifying has a try/catch block, I get a "inconsistant stack height"
>> error. It seems this only occurs if the Try/Catch block is directly
>> around the part i'm modifying. Currently, i'm replacing a
>> constructor from once class type to another. It works perfectly
>> except when there are Try/Catch blocks. For example, if I have
>>
>> 1: public static void main( String [] args ) {
>> 2: System.out.println( "test" );
>> 3: System.out.println( "anotherr test");
>> 4: Shape shape = new Shape();
>> 5: System.out.println( "final test" );
>> 6: }
>>
>> There isn't a problem if the try/catch is around line 2 and 3. Only
>> if it encapsulates line 4, or anything after, will there be the
>> error. For legal reasons i'm unable to show all my actual code so I
>> contrived a very similar example of our insturmenation method that is
>> below. If i'm doing anything wrong/stupid let me know. If you see
>> other problems with my code, feel free to let me know also, i'm
>> always looking for ways to improve. Thanks for any help/suggestions
>> and MUCH thanks to whoever can solve my problem.
>>
>> --vince
>>
>> protected void replaceConstructor( ClassGen cg, String
>> original_class, String new_class ) {
>>
>> boolean refresh = false;
>> ConstantPoolGen cp_gen = cg.getConstantPool();
>> ConstantPool cp = cp_gen.getConstantPool();
>> InstructionFactory factory = new InstructionFactory( cg ,
>> cp_gen );
>>
>> Method [] methods = cg.getMethods();
>> for ( int x=0; x<methods.length; x++ ) {
>> refresh = false;
>> MethodGen method_gen = new MethodGen( methods[x],
>> cg.getJavaClass().getClassName(), cp_gen );
>> Iterator i = method_gen.getInstructionList().iterator();
>> while ( i.hasNext() ) {
>> InstructionHandle handle = ( InstructionHandle )i.next();
>>
>> if ( handle.getInstruction() instanceof INVOKESPECIAL
>> && ( ( INVOKESPECIAL )handle.getInstruction() ).getClassName( cp_gen
>> ).equals( original_class ) && ( ( INVOKESPECIAL
>> )handle.getInstruction() ).getMethodName( cp_gen ).equals( "<init>" )
>> ) {
>> try {
>> INVOKESPECIAL invk = ( INVOKESPECIAL
>> )handle.getInstruction();
>>
>> method_gen.getInstructionList().insert( invk, factory.createInvoke(
>> new_class,
>> "name",
>> new ObjectType( original_class ),
>> invk.getArgumentTypes( cp_gen ),
>> Constants.INVOKESTATIC) );
>>
>> // Delete the old method
>> method_gen.getInstructionList().delete( invk );
>> refresh = true;
>> } catch (
>> org.apache.bcel.generic.TargetLostException e ) {
>> Log.write( "Error", + e.toString() );
>> }
>> }
>> }
>> if ( refresh ) {
>> method_gen.stripAttributes( false );
>> method_gen.setMaxStack();
>> method_gen.setMaxLocals();
>> cg.replaceMethod( methods[x], method_gen.getMethod() );
>> }
>> }
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [email protected]
>> For additional commands, e-mail: [email protected]
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>
>