because you _didn't_ do it with bcel. You seem to think that changing
invokespecial ArrayList.<init> to invokestatic ArrayList.getArrList is the same as changing new ArrayList() to ArrayList.getArrList
It's not. new ArrayList() compiles to new ArrayList dup invokespecial ArrayList.<init>
(as shown here: http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#9839
)
ArrayList.getArrList() compiles to invokestatic ArrayList.getArrList
So you can't expect to replace 1 instruction from the first sequence with the second sequence and expect things to be ok. replace the whole sequence, or at least pop the extra ArrayLists off the stack.
Vincent Marquez wrote:
Well, i've been playing with this a little in my spare time and there is still a problem. This may be due to my lack of experience in regards to Java's exception handling, but I don't understand why the code would compile and run when I manually change the ArrayList() constructor to a static method returning a new ArrayList, but not when I do it with BCEL. For reference, here is the original code I wrote by hand for the test case:
-------------------------------------------------------------------------------------------------
public static java.util.ArrayList getArrList();
Code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: areturn
public static void main(java.lang.String[]);
Code:
0: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #5; //String test
5: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: new #2; //class java/util/ArrayList
11: dup
12: invokespecial #3; //Method java/util/ArrayList."<init>":()V
15: astore_1
16: goto 20
19: astore_1
20: return
Exception table:
from to target type
8 16 19 Class java/lang/Exception
----------------------------------------------------------------------------------
and the actual java that was compiled to whats up above:
public static void main( String [] args ) {
System.out.println( "test" );
try {
ArrayList arr = new ArrayList( );
} catch ( Exception e ) {
}
}
-----------------------------------------------------------------------------------
Next, I ran it through my BCEL program that modifies it. The output is exactly the same except for 13, which is now
13: invokestatic #41; //Method java/util/ArrayList.getArrList:(I)Ljava/util/ArrayList;
Here is the output again from the "after BCEL modification"
-------------------------------------------------------------------------------------
public static void main(java.lang.String[]);
Code:
0: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #5; //String test
5: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: new #2; //class java/util/ArrayList
11: dup
12: invokestatic #37; //Method java/util/ArrayList.getArrList:()Ljava/util/ArrayList;
15: astore_1
16: goto 20
19: astore_1
20: return
Exception table:
from to target type
8 16 19 Class java/lang/Exception
------------------------------------------------------------------------------------------------
I'm confused because I don't see how changing that one line would cause the class to not be verified correctly. I'm also stumped because when I change my code manually to the following, compile, and run, it works fine.
try {
ArrayList arr = getArrList();
} catch ( Exception e ) {
}
Is this a problem with BCEL or a problem with my lack of Exception knowledge? I'm leaning towards the later, but I'm quite stumped. If anyone has any clues or ideas on how I could solve this problem, I'd appreciate it very much. Thank you for your time.
--vince
Andrew Huntwork wrote:
Vincent Marquez wrote:
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
is this right? try {
astore_1 getstatic java.lang.System.out Ljava/io/PrintStream; ldc "test test test" invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
} catch(...
is this offset 20?
return =======================================================
if i'm right then your problem is...
=============== 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
this dup ^. It leaves an extra object on the stack that will be there when you get to 20 via the goto -> 20 below but not if you get there via the exception catch block. the stack in an exception handler is always just the exception object. everything on the stack at the instruction that threw the exception gets tossed.
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
====================================================================
--------------------------------------------------------------------- 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]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
