-
1. Re: JBossRetro cannot replace final reference to StringBuild
pgier Apr 1, 2009 9:51 AM (in response to kfinkels)Can you file a JIRA issue for this?
https://jira.jboss.org/jira/browse/JBBUILD
If you create a patch that fixes it, I'd be happy to apply it. If not, it may take a while for it to be fixed. -
2. Re: JBossRetro cannot replace final reference to StringBuild
adrian.brock Apr 1, 2009 10:46 AM (in response to kfinkels)This looks to be a problem in javassist rather jboss-retro
The following test classpublic class Test { public static void main(String[] args) throws Exception { final StringBuilder s = new StringBuilder("hello"); System.out.println(s.toString()); } }
When run through the following simple javassist program to change the class namesimport java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import javassist.bytecode.ClassFile; public class Rename { public static void main(String[] args) throws Exception { DataInputStream dis = new DataInputStream(new FileInputStream("Test.class")); ClassFile cf = new ClassFile(dis); cf.renameClass("Test", "Test1"); cf.renameClass("java/lang/StringBuilder", "test/StringBuilder"); DataOutputStream dos = new DataOutputStream(new FileOutputStream("Test1.class")); cf.write(dos); } }
Isn't renaming the literal used by the local variable table
I think because it is marked as type "Asciz" rather than "class"?
BEFORE$ javap -c -verbose Test Compiled from "Test.java" public class Test extends java.lang.Object SourceFile: "Test.java" minor version: 0 major version: 49 Constant pool: const #1 = Method #9.#20; // java/lang/Object."<init>":()V const #2 = class #21; // java/lang/StringBuilder const #3 = String #22; // hello const #4 = Method #2.#23; // java/lang/StringBuilder."<init>":(Ljava/lang/String;)V const #5 = Field #24.#25; // java/lang/System.out:Ljava/io/PrintStream; const #6 = Method #2.#26; // java/lang/StringBuilder.toString:()Ljava/lang/String; const #7 = Method #27.#28; // java/io/PrintStream.println:(Ljava/lang/String;)V const #8 = class #29; // Test const #9 = class #30; // java/lang/Object const #10 = Asciz <init>; const #11 = Asciz ()V; const #12 = Asciz Code; const #13 = Asciz LineNumberTable; const #14 = Asciz main; const #15 = Asciz ([Ljava/lang/String;)V; const #16 = Asciz Exceptions; const #17 = class #31; // java/lang/Exception const #18 = Asciz SourceFile; const #19 = Asciz Test.java; const #20 = NameAndType #10:#11;// "<init>":()V const #21 = Asciz java/lang/StringBuilder; const #22 = Asciz hello; const #23 = NameAndType #10:#32;// "<init>":(Ljava/lang/String;)V const #24 = class #33; // java/lang/System const #25 = NameAndType #34:#35;// out:Ljava/io/PrintStream; const #26 = NameAndType #36:#37;// toString:()Ljava/lang/String; const #27 = class #38; // java/io/PrintStream const #28 = NameAndType #39:#32;// println:(Ljava/lang/String;)V const #29 = Asciz Test; const #30 = Asciz java/lang/Object; const #31 = Asciz java/lang/Exception; const #32 = Asciz (Ljava/lang/String;)V; const #33 = Asciz java/lang/System; const #34 = Asciz out; const #35 = Asciz Ljava/io/PrintStream;; const #36 = Asciz toString; const #37 = Asciz ()Ljava/lang/String;; const #38 = Asciz java/io/PrintStream; const #39 = Asciz println; { public Test(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public static void main(java.lang.String[]) throws java.lang.Exception; Code: Stack=3, Locals=2, Args_size=1 0: new #2; //class java/lang/StringBuilder 3: dup 4: ldc #3; //String hello 6: invokespecial #4; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 9: astore_1 10: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream; 13: aload_1 14: invokevirtual #6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 17: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 20: return LineNumberTable: line 5: 0 line 6: 10 line 7: 20 Exceptions: throws java.lang.Exception }
AFTER[ejort@warjort final-test]$ javap -c -verbose Test1 Compiled from "Test.java" public class Test1 extends java.lang.Object SourceFile: "Test.java" minor version: 0 major version: 49 Constant pool: const #1 = Method #9.#20; // java/lang/Object."<init>":()V const #2 = class #41; // test/StringBuilder const #3 = String #22; // hello const #4 = Method #2.#23; // test/StringBuilder."<init>":(Ljava/lang/String;)V const #5 = Field #24.#25; // java/lang/System.out:Ljava/io/PrintStream; const #6 = Method #2.#26; // test/StringBuilder.toString:()Ljava/lang/String; const #7 = Method #27.#28; // java/io/PrintStream.println:(Ljava/lang/String;)V const #8 = class #40; // Test1 const #9 = class #30; // java/lang/Object const #10 = Asciz <init>; const #11 = Asciz ()V; const #12 = Asciz Code; const #13 = Asciz LineNumberTable; const #14 = Asciz main; const #15 = Asciz ([Ljava/lang/String;)V; const #16 = Asciz Exceptions; const #17 = class #31; // java/lang/Exception const #18 = Asciz SourceFile; const #19 = Asciz Test.java; const #20 = NameAndType #10:#11;// "<init>":()V const #21 = Asciz java/lang/StringBuilder; const #22 = Asciz hello; const #23 = NameAndType #10:#32;// "<init>":(Ljava/lang/String;)V const #24 = class #33; // java/lang/System const #25 = NameAndType #34:#35;// out:Ljava/io/PrintStream; const #26 = NameAndType #36:#37;// toString:()Ljava/lang/String; const #27 = class #38; // java/io/PrintStream const #28 = NameAndType #39:#32;// println:(Ljava/lang/String;)V const #29 = Asciz Test; const #30 = Asciz java/lang/Object; const #31 = Asciz java/lang/Exception; const #32 = Asciz (Ljava/lang/String;)V; const #33 = Asciz java/lang/System; const #34 = Asciz out; const #35 = Asciz Ljava/io/PrintStream;; const #36 = Asciz toString; const #37 = Asciz ()Ljava/lang/String;; const #38 = Asciz java/io/PrintStream; const #39 = Asciz println; const #40 = Asciz Test1; const #41 = Asciz test/StringBuilder; { public Test1(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public static void main(java.lang.String[]) throws java.lang.Exception; Code: Stack=3, Locals=2, Args_size=1 0: new #2; //class test/StringBuilder 3: dup 4: ldc #3; //String hello 6: invokespecial #4; //Method test/StringBuilder."<init>":(Ljava/lang/String;)V 9: astore_1 10: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream; 13: aload_1 14: invokevirtual #6; //Method test/StringBuilder.toString:()Ljava/lang/String; 17: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 20: return LineNumberTable: line 5: 0 line 6: 10 line 7: 20 Exceptions: throws java.lang.Exception }
See the in both:
const #21 = Asciz java/lang/StringBuilder;
So this needs to be raised as a bug in javassist rather than jboss-retro -
3. Re: JBossRetro cannot replace final reference to StringBuild
adrian.brock Apr 1, 2009 11:56 AM (in response to kfinkels)"adrian@jboss.org" wrote:
Isn't renaming the literal used by the local variable table
I think because it is marked as type "Asciz" rather than "class"?
Actually the problem is that renameClass(s) is not processing the
LocalVariableAttributes at all. The LocalVariableAttributes (which is where
the local variable table lives) contains an index into the constant pool for the types.
This needs to be updated to the new value. -
4. Re: JBossRetro cannot replace final reference to StringBuild
adrian.brock Apr 1, 2009 12:00 PM (in response to kfinkels) -
5. Re: JBossRetro cannot replace final reference to StringBuild
chiba Apr 2, 2009 6:15 AM (in response to kfinkels)Yes, renameClass() does not update local variable tables but this should not cause any problems at runtime because the JVM ignore local variable tables.
So I am wondering what is Keren's problem... Keren, could you tell us? -
6. Re: JBossRetro cannot replace final reference to StringBuild
kfinkels Apr 2, 2009 10:29 AM (in response to kfinkels)I have a class like that:
public class LabelTest {
public LabelTest(){
final JFrame frame = new JFrame();
frame.setSize(100, 100);
final StringBuilder builder = createStringBuilder();
JLabel label = new JLabel(builder.toString());
frame.add(label);
frame.setVisible(true);;
}
private StringBuilder createStringBuilder(){
return new StringBuilder("Hello");
}
}
the .class - after the manipulation of jbossretro is still holding the reference to StringBuilder in the Local variable table -
7. Re: JBossRetro cannot replace final reference to StringBuild
chiba Apr 2, 2009 11:31 PM (in response to kfinkels)Hi,
I understand the .class file after the manipulation has a wrong local variable
table but my question is why you think this is a prlbem.
Since the local variable table is not used *at all* at runtime, I guess you saw
another real problem and decompiled the .class file, and then you found the
local variable table contained a wrong entry. Another guess is you are using
another tool that refers to the local variable table.
In either case, I am happy to fix the bug(?) of Javassist but I would also like
to know what is your real problem.
Thank you! -
8. Re: JBossRetro cannot replace final reference to StringBuild
kfinkels Apr 3, 2009 10:41 AM (in response to kfinkels)I has a verify... error and I got an error of with arguments not compatible to the method.
I've looked in the code and it was somehow related to a final field.
I'm not sure that the problem I had was related to the fact that there is a reference in the local variable table to the StringBuilder or something else.
I just wonder if it could cause a problem... -
9. Re: JBossRetro cannot replace final reference to StringBuild
chiba Apr 6, 2009 5:07 AM (in response to kfinkels)Thank you, now I understand.
For further inspection, can you post all the bytecode?public void actionPerformed(java.awt.event.ActionEvent e); 0 new org.jboss.lang.JBossStringBuilder [27] 3 dup 4 ldc <String "Hello"> [29] ....... ....... (I want to know the rest)
Also, I would also like to know the detailed message of the verification error.
Thank you for your cooperation! -
10. Re: JBossRetro cannot replace final reference to StringBuild
kfinkels May 14, 2009 1:46 AM (in response to kfinkels)sorry for the late response. I was not able to log into the forum for weeks.
here is the byte code for the following source code:
source code:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
StringBuilder builder = new StringBuilder();
builder.append("Hello");
label = new JLabel(builder.toString());
frame.add(label);
}
});
bytecode after running with jboss-retro:
public void actionPerformed(java.awt.event.ActionEvent e);
0 new org.jboss.lang.[img]JBossStringBuilder [/img][23]
3 dup
4 invokespecial org.jboss.lang.JBossStringBuilder() [25]
7 astore_2 [builder]
8 aload_2 [builder]
9 ldc <String "Hello"> [26]
11 invokevirtual org.jboss.lang.JBossStringBuilder.append(java.lang.String) : org.jboss.lang.JBossStringBuilder [28]
14 pop
15 aload_0 [this]
16 getfield demoAOP.HelloMainFrame$1.this$0 : demoAOP.HelloMainFrame [12]
19 new javax.swing.JLabel [32]
22 dup
23 aload_2 [builder]
24 invokevirtual org.jboss.lang.JBossStringBuilder.toString() : java.lang.String [34]
27 invokespecial javax.swing.JLabel(java.lang.String) [38]
30 invokestatic demoAOP.HelloMainFrame.access$0(demoAOP.HelloMainFrame, javax.swing.JLabel) : void [41]
33 aload_0 [this]
34 getfield demoAOP.HelloMainFrame$1.this$0 : demoAOP.HelloMainFrame [12]
37 invokestatic demoAOP.HelloMainFrame.access$1(demoAOP.HelloMainFrame) : javax.swing.JFrame [47]
40 aload_0 [this]
41 getfield demoAOP.HelloMainFrame$1.this$0 : demoAOP.HelloMainFrame [12]
44 invokestatic demoAOP.HelloMainFrame.access$2(demoAOP.HelloMainFrame) : javax.swing.JLabel [51]
47 invokevirtual javax.swing.JFrame.add(java.awt.Component) : java.awt.Component [55]
50 pop
51 return
Line numbers:
[pc: 0, line: 31]
[pc: 8, line: 32]
[pc: 15, line: 33]
[pc: 33, line: 34]
[pc: 51, line: 35]
Local variable table:
[pc: 0, pc: 52] local: this index: 0 type: new demoAOP.HelloMainFrame(){}
[pc: 0, pc: 52] local: e index: 1 type: java.awt.event.ActionEvent
[pc: 8, pc: 52] local: builder index: 2 type: java.lang.StringBuilder -
11. Re: JBossRetro cannot replace final reference to StringBuild
chiba Jul 2, 2009 7:20 AM (in response to kfinkels)I fixed the bug. Now a local variable table will be correctly updated.