JDK-8039026 : Definitely unassigned field can be accessed
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2014-04-02
  • Updated: 2017-05-17
  • Resolved: 2014-04-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
8u20 b13Fixed 9Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
The following erroneous code compiles on JDK8:

public class Test {
  final int y;
  final int z = this.y; 
  { y = 1; }

If z is instead initialized to 'y', then the appropriate error is given ("variable y might not have been initialized").

This may be related to a javac change for 7004835, whereby 'this.y' (not just 'y') is an "access" to a variable. Of course, since 'this.y' is an access, and the y variable is definitely unassigned at that point, an error is due.

This bug corresponds to spec issue JDK-7004835, which was actioned in JLS7 (see https://jcp.org/aboutJava/communityprocess/maintenance/JLS/JLS-JavaSE7-ChangeLog.html). A CCC request to change the visible behavior of javac is expected.

Very old JCK tests starts failing now under jdk9 nightly: lang/ICLS/icls112/icls11291m1/icls11291m1 lang/ICLS/icls112/icls11291m2/icls11291m2 .... final String i1, i2, i3; ... { // Definite assignment restrictions do not apply to "this.i2". itrace += "/i2=" + this.i2 + "/i2init=" + this.i2init; The JCK tests are not changed since 1998. What spec version does the change apply to? Covered by any CCC requests?

Yes. Within a constructor, instance initializer, or instance variable initializer, the DU/DA analysis for 'this.y' should be the same as for 'y'.

Just to double check, it is my reading of the JLS that this should be rejected as well: public class DU { private final int y; { System.out.println(this.y); y = 0; } } Is that correct?

The point to remember is that JLS 16 traditionally prohibited access to a blank final field via a simple name, but said nothing about [the equally dangerous] access via a primary expression or qualified name. Those formulations are "too hard" to analyze, so they slide by. So it is with the first example, where (t.y == 1 ? this : t).y is "too hard" despite evaluating to this.y which should be an error if written explicitly. The second one should compile. y is definitely assigned after the instance initializer, and hence before the assignment to x.

Here are two more examples which compile. How should they behave? public class Test { final Test t = new Test(); final int y; final int x = (t.y == 1 ? this : t).y; { y = 1; } } public class Test { final int y; { y = 1; } final int x = y; }