Community
Participate
Working Groups
Hi, we have a class with this code: ----------- protected javax.swing.tree.TreeCellEditor createTreeCellEditor() { javax.swing.border.Border oBorder = javax.swing.UIManager.getBorder("Tree.editorBorder"); ZFavoriteTree.CellEditor oEditor = ZFavoriteTree.this.new CellEditor( TreeCellEditor.this.new DefaultTextField(oBorder) ) { public boolean shouldSelectCell(java.util.EventObject oEvent) { boolean retValue = super.shouldSelectCell(oEvent); getComponent().requestFocus(); return retValue; } }; return oEditor; }; ----------- The method is part of an inner protected class 'TreeCellEditor' of the class 'ZFavoriteTree'. The class 'CellEditor' is an inner protected class of the 'ZFavoriteTree', too. If we compile this with the sun jdk 1.3.1_03 it works. But compiled with the eclipse compiler we get a NullPointerException in the line where the CellEditor is being created. If we change the code to ----------- protected javax.swing.tree.TreeCellEditor createTreeCellEditor() { javax.swing.border.Border oBorder = javax.swing.UIManager.getBorder("Tree.editorBorder"); ZFavoriteTree.CellEditor oEditor = new CellEditor( new DefaultTextField(oBorder) ) { public boolean shouldSelectCell(java.util.EventObject oEvent) { boolean retValue = super.shouldSelectCell(oEvent); getComponent().requestFocus(); return retValue; } }; return oEditor; }; ----------- and compile it then with the eclipse compiler, it works. It seems to be a problem with the code generation of the eclipse compiler. BTW: The bug is in build M2 too. Best, Michael
Could you provide a complete test case with all sources for types involved here ? Trying to reproduce I actually found another defect (bug 25229), but could not reproduce yours.
I am guessing this has to do with the fact that the offending code is run dynamically through a constructor invocation. The enclosing instance (ZFavoriteTree.this) isn't bound yet (remember it is accessible through synthetic instance slot this$N). Our codegen is ensuring a null check is performed on the enclosing instance when it is passed to an allocation expression. Can you for instance print the value of ZFavoriteTree.this prior to perform the call and see whether it is null at that stage ? We ensure the enclosing instance is non null, as expected by the spec (javac 1.4 also checks for this). However, once 1.4 compliance is enabled, our compiler will ensure the enclosing instance is non null at that point (since 1.4 VMs are no longer blocking us from doing the right thing - initialize synthetic slots before super constructor invocation; 1.3 VMs were incorrectly reporting a verification error). Now, we might want to be a little more resilient for backward compatibility reason...
If my guess is right, then this small test case should reproduce what you are seeing: public class X { public static void main(String[] arguments) { new X().new X2(); } class X1 { X1(){ this.baz(); } void baz() { System.out.println("X1.baz()"); } } class X2 extends X1 { void baz() { System.out.println("X.this="+X.this); X1 x1 = X.this.new X1(){ void baz(){ System.out.println("X$1.baz()"); } }; } } } - using Eclipse compiler in 1.3 compliant mode X.this=null Exception in thread "main" java.lang.NullPointerException at X$X2.baz(Unknown Source) at X$X1.<init>(Unknown Source) at X$X2.<init>(Unknown Source) at X.main(Unknown Source) --> non-initialized, ensure enclosing instance is non-null as spec'ed. - using Javac 1.3.1 X.this=null X$1.baz() --> non-initialized, but no NPE until actually used - using Javac 1.4.1b18 X.this=null Exception in thread "main" java.lang.NullPointerException at X$1.<init>(X.java:19) at X$X2.baz(X.java:18) at X$X1.<init>(X.java:8) at X$X2.<init>(X.java:15) at X.main(X.java:4) --> they added the null check, but did not fix the codegen to initialize correctly synthetics yet (same behavior as our 1.3 mode) - using Eclipse compiler in 1.3 compliant mode X.this=X@17182c1 X$1.baz() --> synthetic is correctly initialized, null check is in, but now it is fine. (could verify null check is in by using a null enclosing instance instead). Will ensure our 1.3 mode is compliant with javac 1.3. Indeed, this behavior is sound given the VM constraint can make this happen legitimately. Please confirm this is what you are experiencing.
Last test case should have read "using Eclipse compiler in 1.4 compliant mode"
Posted patch did solve the reporter's problem. Fixed (by no longer doing the null check in 1.3 compliant mode).
Verified.