Bug 24400 - Compiler bug or java 'feature' ?
Summary: Compiler bug or java 'feature' ?
Status: RESOLVED WORKSFORME
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: PC Linux
: P3 normal (vote)
Target Milestone: 2.1 M2   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-10-04 12:34 EDT by Luc Bourlier CLA
Modified: 2002-10-08 12:08 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Luc Bourlier CLA 2002-10-04 12:34:54 EDT
I get a problem with the compiled code, but I can't really figure out if it's a
compiler bug or a 'feature' of java.

The execution of the following code generates a NullPointerException in a method
added by the compiler.

public class Test {
  abstract class Super {
    public Super() {
      hop();
    }
    abstract void hop();
  }

  class Inner extends Super {
    public Inner() {
      super();
    }
    public void hop() {
      System.out.println(fField);
    }
  }
  
  private Object fField;
  public static void main(String[] args) {
    Test3 test= new Test3("foo");
    Inner inn= test.new Inner();
    System.out.println("Test ...");
  }
  public Test3(Object field) {
    fField= field;
  }
}

The exception stack trace :

Exception in thread "main" java.lang.NullPointerException
  at Test3.access$0(Test3.java:23)
  at Test3$Inner.hop(Test3.java:19)
  at Test3$Super.<init>(Test3.java:6)
  at Test3$Inner.<init>(Test3.java:15)
  at Test3.main(Test3.java:27)

The problem is : the constructor of Inner calls the constructor of Super which
calls hop() on 'this' instance. By polymorphism, Inner#hop() is called. In
Inner#hop(), we try to access to fField, which in a field of Test. For get the
value of this field, the method access$0(..) is called. This method returns the
enclosing instance of the given object, the field this$0 of the given object.
But in this case, this field is not yet initialised. So the methode returns
null. For get the value of fField, a getField instruction is executed on the
return value. As the value is null, the VM throws an exception.

The question is: does this code is correct, and the compiler should manages the
case ? or is it a weakness in java ?

I tried to get an answer from the java specs, but I didn't find any good
information.
In the java lang spec, at
http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#229267,
there is something about anonymous classes in constructors, but it's not really
relevant.
The VM spec says to look at
http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html
In this document, there is one note (end of the first bloc in 
http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc2.html)
which says that some implementations delay the initialisation of this$0 after
the call of the super constructor, so the problem can occurs.

But I didn't find anything saying that the initialisation of this$0 can't be
done before the execution of the super constructor.


For info, javac from the Sun 1.4.1 sdk generates the same type of code and
throws the same NPE.
Comment 1 Philipe Mulet CLA 2002-10-08 12:08:00 EDT
This is a known limitation of innerclass emulations, due to the fact that most 
VMs forbide initializing synthetic slots (this$0) prior to performing super 
constructor calls. This is precisely the scenario you are running into.

Newer VMs will no longer reject code where synthetics are initialized before 
the super call, therefore if you toggle our compiler in 1.4 compliant mode, it 
will produce bytecodes doing the proper generation.

If toggling our compiler in 1.4 mode, you'll be able to run on 1.4 JREs and get:
foo
Test ...
Comment 2 Philipe Mulet CLA 2002-10-08 12:08:14 EDT
Closing