More‎ > ‎

Findbugs™ Warnings By Example - @Nonnull and @CheckReturnValue of JSR-305

BY MARKUS SPRUNCK


This tutorial describes selected warnings of Findbugs with Java sample code. Here JSR305 related (@Nonnull and @CheckReturnValue) warnings of FindBugs™ are in the center of attention. The following 3 warnings are covered in this article: 

- NP_NONNULL_RETURN_VIOLATION 
- NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE 
- RV_RETURN_VALUE_IGNORED

Basics about @Nonnull and @CheckReturnValue Annotations from JSR305

For static code analysis tools it is sometimes difficult to correctly detect not null usage. With JSR305 the developer can help Findbugs in the analysis. I strongly recommend to check each possible NullPointerException, but sometimes it is a good idea not to suppress each unexpected behavior.

Nathaniel Ayewah and William Pugh [1] said:

"Mistakes that manifest themselves by throwing exceptions are generally preferable to manifestations that silently and occasionally generate corrupted data or performance bottlenecks." 

The use of @Nonnull and @CheckReturnValue annotations from JSR305 help to express the needs for null and return value checks. It is a good practice that the developer describes the expected behavior of the implementation for the later use and the static code analysis.

Motivation for the 'Findbugs™ Warnings By Example' Series













The FindBugs™ bug descriptions of the online documentation are concise and well written.

Unfortunately, some parts of the descriptions are not easy to understand (even for experienced Java developers). It can be difficult to understand the exact root cause for a warning and/or to find the correct way of fixing.

To be honest - at least I had problems with some warnings in the last years. Quite often, I found no helping sample code in the web. The main weakness of the bug descriptions is, that it uses seldom sample code to demonstrate the wrong and correct situation. 

Example Code

Findbugs™ (Version 2.0.1-rc2) will show all warnings with the minimum rank 13 (of concern) and confidence Low of the Findbugs™ Eclipse Plugin (Version 2.0.1.20120511). The code has been compiled with JDK 1.6.0_24. You will need the jsr305.jar (Findbugs lib directory) file in the class path.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.sw_engineering_candies;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.meta.When;

public class FindbugsWarningsByExample4 {

	public static void main(final String[] args) {

		System.out.println("Findbugs Sample for NP_NONNULL_RETURN_VIOLATION ");
		// Confidence: High, Rank: Scary (6)
		// Pattern: NP_NONNULL_RETURN_VIOLATION
		// Type: NP, Category: CORRECTNESS (Correctness)
		//
		// WRONG code, but CORRECT warning in method
		String tempA = FindbugsWarningsByExample4.getSometimesNullValue_Nonnull_Annotation_WRONG();
		try {
			System.out.println("   - " + tempA.length());
		} catch (final NullPointerException e) {
			System.out.println("   - " + e.getMessage());
		}
		// CORRECT code
		String tempB = FindbugsWarningsByExample4.getNeverNullValue_Nonnull_Annotation_CORRECT();
		System.out.println("   - " + tempB.length());

		System.out.println("\nFindbugs Sample for NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE");
		// Confidence: Normal, Rank: Troubling (13)
		// Pattern: NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE
		// Type: NP, Category: STYLE (Dodgy code)
		//
		// WRONG code but no warning
		String tempC = FindbugsWarningsByExample4.getSometimesNullValue_WithoutAnnotation_WRONG();
		try {
			System.out.println("   - " + tempC.length());
		} catch (final NullPointerException e) {
			System.out.println("   - " + e.getMessage());
		}
		// WRONG code, but CORRECT warning form Findbugs
		String tempD = FindbugsWarningsByExample4
				.getSometimesNullValue_Notnull_MaybeNull_Annotation_CORRECT();
		try {
			// Next line should show NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE
			System.out.println("   - " + tempD.length());
		} catch (final Exception e) {
			System.out.println("   - " + e.getMessage());
		}

		System.out.println("\nFindbugs Sample for RV_RETURN_VALUE_IGNORED ");
		// Confidence: Low, Rank: Scary (8)
		// Pattern: RV_RETURN_VALUE_IGNORED
		// Type: RV, Category: CORRECTNESS (Correctness)
		//
		// NO RETURN CHECK - without Findbugs warning
		FindbugsWarningsByExample4.getSometimesNullValue_NonWithCheckReturnValueAnnotation_WRONG();
		//
		// NO RETURN CHECK - with Findbugs warning
		// Next line should show RV_RETURN_VALUE_IGNORED
		FindbugsWarningsByExample4.getWithCheckReturnValue_Annotation_CORRECT();
		//
		// RETURN CHECK - CORRECT code
		final String tempE = FindbugsWarningsByExample4.getWithCheckReturnValue_Annotation_CORRECT();
		System.out.println("   - " + tempE);
	}

	public static @Nonnull
	String getNeverNullValue_Nonnull_Annotation_CORRECT() {
		return Math.random() < 0.5 ? "first value" : "second value";
	}

	public static @Nonnull
	String getSometimesNullValue_Nonnull_Annotation_WRONG() {
		// Next line should show NP_NONNULL_RETURN_VIOLATION
		return Math.random() < 0.5 ? null : "second value";
	}

	public static @Nonnull(when = When.MAYBE)
	String getSometimesNullValue_Notnull_MaybeNull_Annotation_CORRECT() {
		return Math.random() < 0.5 ? null : "second value";
	}

	public static String getSometimesNullValue_WithoutAnnotation_WRONG() {
		return Math.random() < 0.5 ? null : "second value";
	}

	public static String getSometimesNullValue_NonWithCheckReturnValueAnnotation_WRONG() {
		return Math.random() < 0.5 ? null : "second value";
	}

	@CheckReturnValue
	public static String getWithCheckReturnValue_Annotation_CORRECT() {
		return Math.random() < 0.5 ? null : "second value";
	}

}

The program should print the following to the standard output:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Findbugs Sample for NP_NONNULL_RETURN_VIOLATION 
   - null
   - 12

Findbugs Sample for NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE
   - null
   - null

Findbugs Sample for RV_RETURN_VALUE_IGNORED 
   - null

References

[1]  Null Dereference Analysis in Practiceby Nathaniel Ayewah and William Pugh; PASTE '10 Proceedings of the 9th ACM SIGPLAN-SIGSOFT; June 5–6, 2010, Toronto, Ontario, Canada;  

Sponsored Link