Bug 141830 - [1.3][compiler] Severe runtime errors with anonymous classes
Summary: [1.3][compiler] Severe runtime errors with anonymous classes
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: 3.3 M5   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-05-15 14:00 EDT by Toby Ho CLA
Modified: 2007-02-13 08:28 EST (History)
1 user (show)

See Also:


Attachments
Proposed fix (5.56 KB, patch)
2007-01-26 14:37 EST, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Toby Ho CLA 2006-05-15 14:00:34 EDT
run the code below:
<code>
abstract class TemplateClass {
   
    public TemplateClass(){
        doIt();
    }
    
    public void doIt(){
        doItPart();
    }
    
    protected abstract void doItPart();
    
}

public class Bug {

    String field = "I am a field of the containing class.";
    
    public void execute(final String finalArg){
        new TemplateClass(){
            protected void doItPart() {
                System.out.println("containing class: " + Bug.this);
                System.out.println("finalArgment: " + finalArg + "\n");
                System.out.println("field: " + field + "\n");
            }
            
        };
    }
    
    public static void main(String[] arg){
        new Bug().execute("I am a final Argument.");
    }
}
</code>
and you get the following output:
<output>
containing class: null
finalArgment: null

Exception in thread "main" java.lang.NullPointerException
	at com.manheim.point.dao.Bug$1.doItPart(Bug.java:27)
	at com.manheim.point.dao.TemplateClass.doIt(Bug.java:11)
	at com.manheim.point.dao.TemplateClass.<init>(Bug.java:7)
	at com.manheim.point.dao.Bug$1.<init>(Bug.java:23)
	at com.manheim.point.dao.Bug.execute(Bug.java:23)
	at com.manheim.point.dao.Bug.main(Bug.java:34)
</output>

I have tested this code with eclipse versions 3.1, 3.1.2, 2.1, and javac and the error only happens with eclipse versions 3.1 and 3.1.2. The problems are the following:
1. The first print statement shows that Bug.this is null. This show never be possible in Java.
2. The second print statement shows that a final argument reference from the execute() method is null when it should contain the value "I am a final Argument."
3. The third statement merely reiterates problem 1, in that if you try to reference a field in Bug.this, you get a NPE.
Comment 1 Olivier Thomann CLA 2006-05-15 23:15:56 EDT
This is fixed in HEAD.
I get:
containing class: Bug@360be0
finalArgment: I am a final Argument.

field: I am a field of the containing class.
Comment 2 Philipe Mulet CLA 2006-05-16 05:22:48 EDT
Actually, the problem is still there. The steps were incomplete I believe, it only occurs when -source 1.3 is specified.

Toby - can you confirm this ?
Comment 3 Philipe Mulet CLA 2006-05-16 05:25:18 EDT
When using javac 1.3.1 or 1.4.2 with -source 1.3, I also reproduce the issue.
Javac 1.5.0 -source 1.3 no longer reproduces.
Comment 4 Philipe Mulet CLA 2006-05-16 05:27:19 EDT
Exact Javac versions were:
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_01a)
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_10-ea-b01)
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b02)
Comment 5 Philipe Mulet CLA 2006-05-16 06:14:37 EDT
Actually, this behavior is intended. Post 1.4 source level, synthetic initializations occur prior to explicit constructor call.
In clear, the super constructor call from the anonymous default constructor is calling back into the anonymous before the field this$0 (representing Bug.this) got a chance to be initialized. The offending runtime path is: Bug$1()->TemplateClass()->TemplateClass.doIt()->Bug$1.doItPart().

Prior to source 1.4, the code of the anonymous constructor does:
<init>(Bug this$0) {
   super();
   this.this$0 = this$0;
   ...
}
post 1.4, VMs allow better support of synthetics, and allow:
<init>(Bug this$0) {
   this.this$0 = this$0;
   super();
   ...
}

Need to double check whether our configuration strategy is valid or not. It feels like from 1.5 on javac is producing code as if source level was >= 1.4 wrt to synthetic initializations.

Comment 6 Philipe Mulet CLA 2006-05-16 06:16:42 EDT
I believe the configuration behavior should be based on target level, rather than source level. When using javac with -source 1.3 -target 1.3, it issues the NPE as well.

Comment 7 Philipe Mulet CLA 2006-05-16 06:20:06 EDT
Actually, we already toggle behavior based on -target setting.
So we are fine there.

Now, we seem to have a mismatch on the batch compiler itself.
When using -1.5 -source 1.3, javac leaves the target at 1.5 !?

Toby: the proper solution is for you to specify explicitly using a -1.4 target or above in your compiler settings.
Comment 8 Philipe Mulet CLA 2006-05-16 06:24:31 EDT
javac 1.3 -source 1.3, sets the default target to 1.1
javac 1.4 -source 1.3, sets the default target to 1.2
javac 1.5 -source 1.3, sets the default target to 1.4
javac 1.6 -source 1.3, sets the default target to 1.4

We should revisit our defaults to match these.
For current time being, Toby, please make these settings explicit.
Comment 9 Philipe Mulet CLA 2006-05-16 06:32:58 EDT
Olivier - pls check all source levels, and provide a patch to the batch compiler.
          ideally, you should paste here a matrix of defaults.

Martin - there may need to be some alignments in UI.

Likely something for 3.3 at best.
Comment 10 Toby Ho CLA 2006-05-16 10:02:04 EDT
(In reply to comment #2)
> Actually, the problem is still there. The steps were incomplete I believe, it
> only occurs when -source 1.3 is specified.
> 
> Toby - can you confirm this ?
> 
I have been using source level 1.4.
Comment 11 Olivier Thomann CLA 2007-01-26 14:01:40 EST
(In reply to comment #9)
> Olivier - pls check all source levels, and provide a patch to the batch
> compiler.
>           ideally, you should paste here a matrix of defaults.
List of defaults:

javac 1.3:

-source option doesn't exist.
  default target 1.1

javac 1.4:
-source 1.2, default target 1.2
-source 1.3, default target 1.2
-source 1.4, default target 1.4

javac 1.5:
-source 1.2, default target 1.4
-source 1.3, default target 1.4
-source 1.4, default target 1.4
-source 1.5, default target 1.5

javac 1.6:

-source 1.2, default target 1.4
-source 1.3, default target 1.4
-source 1.4, default target 1.4
-source 1.5, default target 1.6
-source 1.6, default target 1.6

javac 1.7:

-source 1.2, default target 1.4
-source 1.3, default target 1.4
-source 1.4, default target 1.4
-source 1.5, default target 1.6
-source 1.6, default target 1.6
-source 1.7, default target 1.7
Comment 12 Olivier Thomann CLA 2007-01-26 14:37:59 EST
Created attachment 57618 [details]
Proposed fix
Comment 13 Olivier Thomann CLA 2007-01-26 14:51:52 EST
(In reply to comment #10)
> I have been using source level 1.4.
You must have the target set to 1.1 and this would explain the error.
I adjusted the compiler's defaults.
I'll released once all the tests are done.
Comment 14 Olivier Thomann CLA 2007-01-26 14:54:08 EST
(In reply to comment #9)
> Martin - there may need to be some alignments in UI.
Martin,

The UI doesn't allow the source to be 1.2. This is allowed by the compiler and javac. Might not be a big deal since source 1.2 doesn't add any value.
Comment 15 Olivier Thomann CLA 2007-01-26 15:43:35 EST
Released for 3.3M5.
Added regression tests org.eclipse.jdt.core.tests.compiler.regression.BatchCompilerTest#test107/121
Comment 16 Olivier Thomann CLA 2007-01-26 15:44:16 EST
(In reply to comment #14)
> The UI doesn't allow the source to be 1.2. This is allowed by the compiler and
> javac. Might not be a big deal since source 1.2 doesn't add any value.
Our batch compiler doesn't allow 1.2 as well for the source value. So this is not something we should change.
Comment 17 Eric Jodet CLA 2007-02-06 04:54:26 EST
Verified for 3.3 M5 using build I20070205-0009
Comment 18 Martin Aeschlimann CLA 2007-02-13 06:06:35 EST
please file a bug against jdt.ui if I need to change something.
Comment 19 Olivier Thomann CLA 2007-02-13 08:28:49 EST
As long as you respect the defaults, you are fine. I haven't check them on the UI side.