📜 ⬆️ ⬇️

Win NPE hell in Java without using IntelliJ IDEA

Denial of responsibility


First, the material appeared because I wanted to quickly explain to Hindus colleagues what null analysis is, what it is good for, and why it is necessary to overcome corporate laziness right now and start using this analysis in projects. There was no article containing complete systematized information about the item without reference to the IDE, so I had to write it myself. And although, as a result of complete systematization, it did not work out, I still wanted to share the material with a wider audience. There will be a minimum of text and a lot of images.

Secondly, the resource already has an excellent article tr1cks , dedicated to IntelliJ IDEA, which reinforces the already persistent impression that IDEA is very good, and Eclipse is for the poor (which has become the talk of the town). To keep balance, I'll focus on Eclipse.

I will use the FindBugs project annotations (also known as JSR 305 annotations) due to the lack of linking them to a specific development environment (fans can use org.eclipse.jdt.annotation.* And org.jetbrains.annotations.* ), As well as because they are available at Maven Central. For those who use Maven, just add the following to the <dependencies/> section:
')
 <dependency> <groupId>com.google.code.findbugs</groupId> <artifactId>jsr305</artifactId> <version>3.0.0</version> </dependency> 

Just in case, I stipulate that

  @Nonnull public String getName() { // ... } 

and

  public @Nonnull String getName() { // ... } 

- these are two absolutely equivalent constructions, although in some cases two variants of the obtained bytecode may differ by exactly 1 byte (by the way, how do you think - why?)

Eclipse


All of the following has been tested on Eclipse 4.4 (Luna). At the same time, if my memory serves me, the described functionality was already present in 3.8 (and possibly even earlier).

Customization




False positive diagnosis


Few people will be glad if the diagnosis is wrong. Fortunately, it is possible to say: "Doctor, you were drunk and analyzed someone else's blood!"

Problem


The picture shows that Eclipse is unable to determine that (in a single-threaded scenario, of course) the field cannot be null at the time of the hashCode() call:


Yes, of course, we can mark the entire method with @SuppressWarnings("null") , but this will @SuppressWarnings("null") all the benefits of null analysis.

Workaround 0


Add assert :


Workaround 1


Longer, but also possible. Let's pull out the field value into a local variable, mark it as @Nonnull and continue to work with it:


Underwater rocks


Starting with Java 1.8, a new type of metadata is supported - type annotations (see JSR 308 ) - and, accordingly, annotations are required to explicitly specify @Target . FindBugs annotations do not meet this requirement. Therefore, if you use Eclipse up to 4.4 inclusive (Luna) and Java 1.8, then null analysis using FindBugs annotations will not work ( bug # 435805 ). In general, in this case, go better to Eclipse 4.5 (Mars).

Reading at home




IDEA


IntelliJ IDEA supports null analysis, it seems, since the beginning of time (check Constant conditions & exceptions and @ NotNull / @Nullable problems ).




What is nice is that the medium out of the box knows about a number of suitable annotations, including JSR 305:


The only pity is that, unlike Eclipse, annotations on the entire package (like @NonNullByDefault or @ParametersAreNonnullByDefault ) are not supported.

Update


Starting with build 138.1372 ( IDEA-125281 ), @ParametersAreNonnullByDefault and @ParametersAreNullableByDefault at the package level are recognized and analyzed, although they do not appear anywhere in the settings (thanks to Borz ). Moreover, the functionality appears to be present in IDEA 13.1.6 (build 135.1306).

Netbeans


NetBeans has been supporting null analysis since 7.3, see next. article english .

Remarks


If you use not only IDE, but also FindBugs, then methods that potentially return null should be marked not only as @Nullable , but also as @CheckForNull — FindBugs will “calm down” only if it sees @CheckForNull .

Nice bonuses nishtyaki side effects


This is a lyrical deviation from the topic, but it tells about the immediate benefits that the introduction of analysis in project X has brought. More precisely, it has helped to identify the giants of the unit tests.

Long ago, there were tests that did not fall, but were not very cleverly written. Yes, you were not mistaken, this is JUnit 3:

 public void test() throws Exception { final Calendar calendar = myVeryCleverNonStandardApiCall(); final int year = calendar.get(Calendar.YEAR); assertEquals(1997, year); assertEquals("1.1", System.getProperty("java.specification.version")); } 

It took only a few years, and it was noticed that the tests broke. That is, it is still compiled, but does not work anymore. The tests were "repaired", so much so that the mosquito of the nose is not undermined. In short, no one noticed:

 public void test() throws Exception { final Calendar calendar = myVeryCleverNonStandardApiCall(); final int year = calendar.get(Calendar.YEAR); // assertEquals(1997, year); // assertEquals("1.1", System.getProperty("java.specification.version")); } 

After a few more years, it even stopped compiling, and good statistics were still needed. The tests were “repaired” again. Since it was impossible to get rid of NPE, and throwing out a large piece of code would have attracted attention, the old test was disguised, and a new one was introduced with a second delay to distract eyes:

 public void test() throws Exception { Thread.sleep(1000); } public void _test() throws Exception { final Calendar calendar = null; //myVeryCleverNonStandardApiCall(); final int year = calendar.get(Calendar.YEAR); // assertEquals(1997, year); // assertEquals("1.1", System.getProperty("java.specification.version")); } 

Conclusion?

Sometimes it makes sense to raise the level of Null pointer access and Potential null pointer access to “Error” even for legacy code. Especially for legacy code. You can’t even imagine what the bison who have created your product literally from scratch twenty years ago and safely gone into some Google or Amazon ten years ago are capable of.

Wishes


If there are people among readers who use C #, please comment, is the problem for C # relevant in the light of having such a nice thing as Nullable , and, if so, by what means?

Source: https://habr.com/ru/post/204518/


All Articles