This page discusses current work on improving the static null analysis of the JDT compiler.

+

This page describes ongoing work on improving the static null analysis of the JDT compiler.

−

The initial master bug for this work was {{FixedBug|186342}}.

+

The initial master bug for this work was {{FixedBug|186342}}, this part has been released for Eclipse Juno (JDT 3.8).

Line 39:

Line 39:

* analysis might be more precise than some existing tools provide, because the actual flow analysis in the JDT compiler is already pretty strong (unproven claim).

* analysis might be more precise than some existing tools provide, because the actual flow analysis in the JDT compiler is already pretty strong (unproven claim).

−

A preparatory discussion of the design space can be found here: [[/Brainstorming]].

[[Image:Video.png]] See also the recording of this [http://eclipsecon.org/europe2011/ ECE 2011] [http://eclipsecon.org/europe2011/sessions/bye-bye-npe session]: '''[http://www.fosslc.org/drupal/content/bye-bye-npe Bye, bye, NPE]'''

[[Image:Video.png]] See also the recording of this [http://eclipsecon.org/europe2011/ ECE 2011] [http://eclipsecon.org/europe2011/sessions/bye-bye-npe session]: '''[http://www.fosslc.org/drupal/content/bye-bye-npe Bye, bye, NPE]'''

Line 45:

Line 44:

==Actual Strategy in the JDT==

==Actual Strategy in the JDT==

−

{{note|Work in progress|With [http://download.eclipse.org/eclipse/downloads/drops/S-3.8M4-201112091447/index.php Eclipse 3.8 M4] we released a first version of this feature. We are working on making this easier to consume in Java project setups, and we will also add quick fixes. The implemented features are complete and tested, but e.g. support for annotating fields or APIs from third-party libraries is currently missing.}}

+

{{note|Work in progress|For Eclipse Juno (JDT 3.8) we released a first version of this feature. The implemented features are complete and tested, but further improvements are still in the pipe line (see [[#Status]]).}}

−

By default the JDT does not support inter-procedural null analysis, however, starting with 3.8 M4 the JDT can be configured to use annotations for extended null checking.

+

By default the JDT does not support inter-procedural null analysis, however, starting with 3.8 the JDT can be configured to use annotations for extended null checking.

+

+

Up-to-date documentation for the annotation-based null analysis and its new configuration options can be found in the Eclipse help (Eclipse 3.8 and greater):

Null annotations in method signatures can be interpreted as [[/Null Contracts|null contracts]], however, a more general approach considers null annotations as an extension of the type system. Eventually - that is once JSR 308 can be used - all type references should either include or exclude null, which allows for complete checking of any possible dereferencing of null. In other words, a fully annotated program which passes the type checker will never raise an NPE at runtime.

Null annotations in method signatures can be interpreted as [[/Null Contracts|null contracts]], however, a more general approach considers null annotations as an extension of the type system. Eventually - that is once JSR 308 can be used - all type references should either include or exclude null, which allows for complete checking of any possible dereferencing of null. In other words, a fully annotated program which passes the type checker will never raise an NPE at runtime.

−

To achieve this guarantee two annotations are used. The specific annotations types can be selected as a preference, but the following defaults are provided (see [[#Compiler configuration explained]]):

+

To achieve this guarantee two annotations are used. The specific annotations types can be selected as a preference, but the following defaults are provided:

The above rules imply that the value from a @NonNull variable can be bound to a variable annotated with @Nullable, but the opposite direction is generally illegal.

The above rules imply that the value from a @NonNull variable can be bound to a variable annotated with @Nullable, but the opposite direction is generally illegal.

−

Only after an explicit null check can a @Nullable variable be treated as being @NonNull for the sake of binding to another @NonNull variable or for dereferencing.

+

Only after an explicit null check can a @Nullable variable be treated as being @NonNull for the sake of binding to another @NonNull variable or for dereferencing. For fields the situation is actually more complex &mdash; please read [http://help.eclipse.org/kepler/topic/org.eclipse.jdt.doc.user/tasks/task-using_null_annotations.htm?cp=1_3_9_0_4#fields "The case of fields"].

{{tip|Hints:|Setting the default to <code>@NonNull</code> is the recommended option for new projects, but for existing projects this could require a major clean-up in terms of inserting explicit <code>@Nullable</code> annotations in many locations. Experience shows, that this is a non-trivial task since in existing code the original intention, which parameter/return value should be allowed to be null, is usually blurred. Here starting with no default but adding individual annotations where the intention is clear will cause less disruption. This incremental approach should be seen as a long-term yet low effort task, not only for getting rid of NPEs but also for sorting the responsibilities in the code, which may have eroded over time.}}

+

{{tip|Hints:|Setting the default to <code>@NonNull</code> is the recommended option for new projects, but for existing projects this could require a major clean-up in terms of inserting explicit <code>@Nullable</code> annotations in many locations. Experience shows, that this is a non-trivial task since in existing code the original intention, which parameter/return value should be allowed to be null, is usually blurred. Here starting with no default but adding individual annotations where the intention is clear will cause less disruption. This incremental approach should be seen as a long-term yet low effort task, not only for getting rid of NPEs but also for sorting the responsibilities in the code, which may have eroded over time.<br>For more hints on adpoting these annotations see [[JDT Core/Null Analysis/Adopting Null Annotations|Adoption Null Annotations]].}}

====Cleaning up====

====Cleaning up====

−

{{warning|Temporarily out of service|The following quick fixes were available in the prototype. They are not supported in Eclipse 3.8M4, but the JDT/UI team is currently adopting the implementation so these quick fixes (and more) should be available soon.}}

+

When applying the new analysis to a big existing project, the sheer number of new problems may look intimidating but that's where quick fixes will come to the rescue.

−

+

−

When applying the new analysis to a big existing project, the sheer number of new problems may look intimidating but that's where quickfixes will come to the rescue.

The preference "Use non-null as workspace-wide default" allows to globally change this so that any declaration (currently: method parameters and method return) to which no null annotation applies will be considered as nonnull.

+

To generally avoid these weak semantics you may want to declare that by default all types should be considered as nonnull.

−

For more fine-grained control an additional annotation can be used. The qualified type

+

This is done using the annotation 'NonNullByDefault'. The qualified type

name of this annotation can be configured using the preference "'NonNullByDefault' annotation".

name of this annotation can be configured using the preference "'NonNullByDefault' annotation".

−

The built-in value for these preference is <code>org.eclipse.jdt.annotation.NonNullByDefault</code>.

The built-in value for these preference is <code>org.eclipse.jdt.annotation.NonNullByDefault</code>.

+

* This annotation takes an optional boolean parameter; when set to false this causes the annotation to ''cancel'' a default that may possible apply at the current location. This is useful when, e.g., sub-classing a legacy class without null annotation, where the sub-class sits in a place that would otherwise apply non-null as the default, which would make all overrides incompatible with inherited methods.

* This annotation takes an optional boolean parameter; when set to false this causes the annotation to ''cancel'' a default that may possible apply at the current location. This is useful when, e.g., sub-classing a legacy class without null annotation, where the sub-class sits in a place that would otherwise apply non-null as the default, which would make all overrides incompatible with inherited methods.

Line 171:

Line 162:

method returns and parameters with undefined null status within their scope. (More locations will be supported in the future, but local variables are intentially unaffected by any default).

method returns and parameters with undefined null status within their scope. (More locations will be supported in the future, but local variables are intentially unaffected by any default).

+

==Status==

===Done===

===Done===

−

At the current point the following bugs are resolved:

+

At the current point the following bugs are resolved - functionality is released with Eclipse Juno:

Actual Strategy in the JDT

Work in progressFor Eclipse Juno (JDT 3.8) we released a first version of this feature. The implemented features are complete and tested, but further improvements are still in the pipe line (see #Status).

By default the JDT does not support inter-procedural null analysis, however, starting with 3.8 the JDT can be configured to use annotations for extended null checking.

Up-to-date documentation for the annotation-based null analysis and its new configuration options can be found in the Eclipse help (Eclipse 3.8 and greater):

Specifying nullness

Null annotations in method signatures can be interpreted as null contracts, however, a more general approach considers null annotations as an extension of the type system. Eventually - that is once JSR 308 can be used - all type references should either include or exclude null, which allows for complete checking of any possible dereferencing of null. In other words, a fully annotated program which passes the type checker will never raise an NPE at runtime.

To achieve this guarantee two annotations are used. The specific annotations types can be selected as a preference, but the following defaults are provided:

For any variable who's type is annotated with @NonNull (or the configured equivalent) the following rules apply:

It is illegal to bind null or a value that can be null to the variable. (For fields and local variables this applies to initialization and assignments, for method argument binding a value means to pass an actual argument in a method call).

It is legal and safe to dereference such a variable for accessing a field or a method of the bound object.

For any variable who's type is annotated with @Nullable (or the configured equivalent) the following rules apply:

It is legal to bind null or a value that can be null to the variable (see details above).

It is illegal to dereference such a variable for either field or method access.

The above rules imply that the value from a @NonNull variable can be bound to a variable annotated with @Nullable, but the opposite direction is generally illegal.
Only after an explicit null check can a @Nullable variable be treated as being @NonNull for the sake of binding to another @NonNull variable or for dereferencing. For fields the situation is actually more complex — please read "The case of fields".

Define @NonNull as the default at the granularity of your choice (package/type):

package: add a file package-info.java with contents like this:

@NonNullByDefault package org.my.pack.age;

type: add @NonNullByDefault to the type declaration.

At this point you should see plenty of new errors and warnings

Hints:Setting the default to @NonNull is the recommended option for new projects, but for existing projects this could require a major clean-up in terms of inserting explicit @Nullable annotations in many locations. Experience shows, that this is a non-trivial task since in existing code the original intention, which parameter/return value should be allowed to be null, is usually blurred. Here starting with no default but adding individual annotations where the intention is clear will cause less disruption. This incremental approach should be seen as a long-term yet low effort task, not only for getting rid of NPEs but also for sorting the responsibilities in the code, which may have eroded over time.For more hints on adpoting these annotations see Adoption Null Annotations.

Cleaning up

When applying the new analysis to a big existing project, the sheer number of new problems may look intimidating but that's where quick fixes will come to the rescue.
Currently the following problems offer a quickfix:

Note, that some quick fixes require to modify another compilation unit (file) than the one
where the problem was observed. For these quickfixes the current implementation doesn't
support fixing several equal issues in bulk (for the technical background see
bug 337977).

Defaults at different levels

If no null annotations are used, the compiler uses the original Java semantics,
where the following is legal for all variables of reference types:

assign null, and

dereference without check.

To generally avoid these weak semantics you may want to declare that by default all types should be considered as nonnull.

This is done using the annotation 'NonNullByDefault'. The qualified type
name of this annotation can be configured using the preference "'NonNullByDefault' annotation".
The built-in value for these preference is org.eclipse.jdt.annotation.NonNullByDefault.

This annotation takes an optional boolean parameter; when set to false this causes the annotation to cancel a default that may possible apply at the current location. This is useful when, e.g., sub-classing a legacy class without null annotation, where the sub-class sits in a place that would otherwise apply non-null as the default, which would make all overrides incompatible with inherited methods.

This annotation can be applied to any package, Java type or method and affects all
method returns and parameters with undefined null status within their scope. (More locations will be supported in the future, but local variables are intentially unaffected by any default).

Status

Done

At the current point the following bugs are resolved - functionality is released with Eclipse Juno: