Difference in compilation between ECJ and Javac - BCEL fails to return class fileset [message #487617] |
Wed, 23 September 2009 18:41 |
Mohanraj Loganathan Messages: 3 Registered: September 2009 |
Junior Member |
|
|
Consider the testcase E.java [1]. The constructor tries to print the class A (System.out.println(A.class) ; ). Class A intern has the references to class B, C and D. ANT tries to get the dependant classes for clas E using BCEL library.
When the class E compiled using ECJ, BCEL returns only E as dependent class. Where as javac returns A, B, C, D, E as the dependent classes for class E.
When analyzed further, i found that generated class file itself differing from ecj and javac.
javap output for ecj generated class file :
Max stack=3, Max locals=1
0: aload_0
1: invokespecial java.lang.Object.<init> ()V (11)
4: getstatic java.lang.System.out Ljava/io/PrintStream; (13)
7: getstatic E.class$0 Ljava/lang/Class; (19)
10: dup
11: ifnonnull #39
14: pop
15: ldc "A" (21)
17: invokestatic java.lang.Class.forName (Ljava/lang/String;)Ljava/lang/Class; (23)
20: dup
21: putstatic E.class$0 Ljava/lang/Class; (19)
24: goto #39
27: new <java.lang.NoClassDefFoundError> (29)
30: dup_x1
31: swap
32: invokevirtual java.lang.Throwable.getMessage ()Ljava/lang/String; (31)
35: invokespecial java.lang.NoClassDefFoundError.<init> (Ljava/lang/String;)V (37)
38: athrow
39: invokevirtual java.io.PrintStream.println (Ljava/lang/Object;)V (40)
42: return
javap output for javac generated class file :
Code:
Max stack=2, Max locals=1
0: aload_0
1: invokespecial java.lang.Object.<init> ()V (1)
4: getstatic java.lang.System.out Ljava/io/PrintStream; (2)
7: ldc_w A (3)
10: invokevirtual java.io.PrintStream.println (Ljava/lang/Object;)V (4)
13: return
Reason for BCEL failure to fetch the dependency?
1) ECJ generates the extra codes for the line System.out.prinln(A.class) line. Which is not necessary due to which BCEL is not able to get the Class reference of A from the class file. A is represented as a String and hence during the run time A gets loaded. Especially, look at the lines 15, 17 and 20.
2) Since A gets loaded via Class.forName, ANT/BCEL is not able to detect A as a dependency for class E.
where as ,
RI loads the reference of A in the byte-code itself, hence BCEL is able detect A as a dependency of class E
Why this difference in the bytecode in ECJ? is it a bug ? Any specific reason why ECJ expands the A.class fetching as reflection way.
Can i file a bug for the same?
References:
[1] E.java
Class E {
E() { System.out.println(A.class);}
}
[2] A.java
public class A extends B {
private D d = new D();
}
[3] B.java
public class B extends C { }
[4] D. java
public class D { }
[5] C.java
public class C { }
[6] BCEL Testcase :
Test program for BCEL which gets the dependency of a class --> http://illegalargumentexception.blogspot.com/2008/04/java-fi nding-binary-class-dependencies.html
[Updated on: Wed, 23 September 2009 18:57] Report message to a moderator
|
|
|
|
|
|
|
Powered by
FUDForum. Page generated in 0.03890 seconds