FIndbug not identifying null pointer exception - java

I am using Findbugs integerated with eclipse.
When I run findbugs on my project the below code is not captured for possible null pointer exception.
In the below snippet the object test is prone to null pointer exception which is not identified by findbugs.
#Override
public boolean saveIrr(TestObject test) throws DuplicateRecordException {
boolean status = false
try {
test.getAddDate();
status = adhocMaintPopupMapper.saveIrr(IRRPopupMaint);
} catch (DataIntegrityViolationException e) {
logger.error("Error in Saving!", e);
throw new TransactionDataException("Error in Saving!", e);
}
return status;
}
Is there any configuration change required to make findbugs to identify this?

If you add #Nonnull to the parameter declaration, FindBugs will highlight anywhere you're passing a value that isn't checked for null. If you mark it #CheckForNull, FindBugs will highlight anywhere in the method that you access it without checking for null.
Which you do depends on the method's contract: does it tolerate null or not? Looking at its implementation it does not allow for null without throwing an unexpected exception. Therefore, test should be marked #Nonnull so you can spot incorrect calls.
Update
FindBugs will only check fields, parameters, method return values that are annotated with either #Nonnull or #CheckForNull. Anything without an annotation is assumed #Nullable which tells FindBugs to ignore it.
public boolean saveIrr(#Nonnull TestObject test) { ... }
public void dontCareAboutNull(TestObject value) {
saveIrr(value); // no bug
}
public void mightBeNull(#CheckForNull TestObject value) {
saveIrr(value); // bug
}
For this reason, we apply #Nonnull to all three types of values at the package level. Any value that needs to allow null must be annotated with #CheckForNull. We do not allow the use of #Nullable except in very few corner cases (e.g. #Autowired fields which Spring enforces).

I noticed that you're missing a ; in your code after "boolean status = false", this could be the reason why findbug has problems to parse your code.

OK from what I understood : you want to identify that test has not beeing tested for null. As far as I know there is no way to configure findbugs for doing this. Findbugs can warn you in 2 other cases :
- NP_ARGUMENT_MIGHT_BE_NULL : if you call your method saveIrr with a and argument that has not been tested for null before.
- NP_NULL_INSTANCEOF : if findbug identified that your value is guaranteed to be null at a point.
You can check all the Null Pointer warnings here they are identified with NP: http://findbugs.sourceforge.net/bugDescriptions.html
I think that such a warning would result in a too huge amount of bugs detected : all methods with arguments would give warnings for arguments that would be used before beeing tested.

What you can do is use the annotions of findbugs/jsr305. So if you add #Nullable to the getDate() method in TestObject it may trigger a NP warning. If you want to use those annotions be sure that the jsr305.jar is in your classpath...

Related

How to disable "unnecessary test for null" warning in NetBeans 14?

Short Version
How do i disable the "unnecessary test for null" warning in NetBeans 14 IDE?
Long Version
NetBeans as a well-known bug 1 2 3 4 where it will erroneously tell you that a test for null is unnecessary. For example in the following code:
import javax.validation.constraints.NotNull;
private void doSomething(#NotNull Object o) {
if (o == null) return;
//...do more stuff...
}
The IDE thinks
because the o parameter was tagged as #NotNullo
it must be impossible for o to be null
so it must be that the if statement is unnecessary
This is demonstrably false
The #NotNull annotation is only an IDE hint, not a runtime guarantee.
just because an argument to a method is tagged as #NotNullable
does not mean it cannot be null
You can prove this to yourself by passing null to the doSomething method. (we can even write the test code so the IDE generates no hints or warnings at all!):
Object o = getTestValue();
doSomething(o);
private Object getTestValue()
{
Object o = null;
return o;
}
private void doSomething(#NotNull Object o) {
Objects.requireNonNull(value);
//...do more stuff...
}
And watch doSomething method fail - because o is null - even though it is tagged #NotNull.
Now, there may be other implementations of #NotNull, or other compilers that add runtime checks. I'm not talking about those. The NetBeans IDE 14 warning is wrong, so i need to disable it.
Research Effort
I tried clicking the lightbulb, to hopefully configure the warning:
but it only offers to configure null deference warnings - which i definitely want to keep.
I tried pressing Alt+Enter to bring up more options:
but nothing of value appears:
I tried to let it bring me to the area to configure the Null dereferncing hint:
but it definitely has nothing to do with *unnecessary test for null.
I tried searching for a hint or warning named "null":
but it's not there.
I tried searching for a hint or warning named "unnecessary":
but it's not there.
I tried searching for a hint or warning named "test":
but it's not there.
How to turn it off
Which brings me to my question:
given that NetBeans IDE 14 has no way to turn off "unnecessary test for null" warning
how do i turn off the "unnecessary test for null" warning in NetBeans IDE 14?
Bonus Reading
What does unnecessary test for null mean?
Netbeans tells me to remove null comparison, but that breaks my code ("First thing to note is: NetBeans is wrong")
BugZilla: Bug 226923 - Wrong warning 'the expression is never null'
Bugzilla: Bug 262707 - Add configuration of Nullable/NonNull annotations. Use FQNs or allow to exclude FQNs.
You can turn off the "Unnecessary test for null" warning using the Java annotation #SuppressWarnings("null"). That annotation is found in java.lang, and there is no need for an import.
The OpenJDK Javadoc for SuppressWarnings for JDK 17 states:
Indicates that the named compiler warnings should be suppressed in the
annotated element (and in all program elements contained in the
annotated element) ... As a matter of style, programmers should always
use this annotation on the most deeply nested element where it is
effective. If you want to suppress a warning in a particular method,
you should annotate that method rather than its class.
From the linked documentation to section 9.6.4.5 of the Java Language Specification, #SuppressWarnings appears to do exactly what you want, with my emphasis added:
9.6.4.5. #SuppressWarnings
Java compilers are increasingly capable of issuing helpful "lint-like"
warnings. To encourage the use of such warnings, there should be some
way to disable a warning in a part of the program when the programmer
knows that the warning is inappropriate.
Here's sample code, based on that in the OP:
package suppression;
import javax.validation.constraints.NotNull; // Jakarta EE 8
//import jakarta.validation.constraints.NotNull; // Jakarta EE 9
public class Suppression {
public static void main(String[] args) {
Suppression supp = new Suppression();
Object o = supp.getTestValue();
supp.doSomething(o);
supp.doSomething2(o);
}
Object getTestValue() {
Object o = null;
return o;
}
private void doSomething(#NotNull Object o) {
if (o == null) {
System.out.println("Object is null!");
}
}
#SuppressWarnings("null")
private void doSomething2(#NotNull Object o) {
if (o == null) {
System.out.println("Object is null!");
}
}
}
Here's a screenshot of that code in NetBeans 14 which shows:
The unwanted warning "Unnecessary test for null" is shown on line 22 in method doSomething().
The annotation #SuppressWarnings("null") on line 27 prevents the unwanted warning "Unnecessary test for null" being shown on line 30 in the otherwise identical method doSomething2().
The answer is: it cannot be done.
NetBeans provides no way to disable the unnecessary test for null warning.
Workaround
As other people in other answers have noted:
the value can be null
NetBeans is wrong thinking it cannot be null
The correct way to resolve the (incorrect) warning is to obfuscate the check for null.
Rather than calling:
if (customer == null) { ... }
Instead call:
if (Object.isNull(customer)) { ... }
It is the same thing; except this way NetBeans doesn't realize that you're testing the variable for null, and so doesn't warn you.

AndroidStudio (IDEA) code inspection: "... may produce NullPointerException"

I have following piece of code in Java:
String func() {
Object data = otherFunc();
return data.toString();
}
The otherFunc() is #Nullable function and it can return null. So the IDE highlights toString() method as dangerous, because it can cause NullPointerException.
But in my case, I'm 100% confident about not-null result of otherFunc(). So I added an assert condition there:
String func() {
Object data = otherFunc();
MyAssert.notNull(data, some_debug_info);
return data.toString();
}
There is a null-check verification inside the MyAssert.notNull() call and throwing an exception (with some additional debug info) if it's null.
Android Studio highlights toString() anyway...
Question:
How can I indicate that "data" object can't be null after the MyAssert.notNull() call? Maybe with some #annotations?
There are many similar places in the code, so the solution should modify the assert function only!
IntelliJ's Contract annotations might be what you're looking for.
Annotating your method with #Contract("null, _ -> fail") should tell intelliJ that entering null as the first parameter would cause an exception, meaning any code after the call will assume it is non-null.

Writing unit test for #Nonnull annotated parameter

I have a method like this one:
public void foo(#Nonnull String value) {...}
I would like to write a unit test to make sure foo() throws an NPE when value is null but I can't since the compiler refuses to compile the unit test when static null pointer flow analysis is enabled in IDE.
How do I make this test compile (in Eclipse with "Enable annotation-based null analysis" enabled):
#Test(expected = NullPointerException.class)
public void test() {
T inst = ...
inst.foo(null);
}
Note: In theory the static null pointer of the compiler should prevent cases like that. But there is nothing stopping someone from writing another module with the static flow analysis turned off and calling the method with null.
Common case: Big messy old project without flow analysis. I start with annotating some utility module. In that case, I'll have existing or new unit tests which check how the code behaves for all the modules which don't use flow analysis yet.
My guess is that I have to move those tests into an unchecked module and move them around as I spread flow analysis. That would work and fit well into the philosophy but it would be a lot of manual work.
To put it another way: I can't easily write a test which says "success when code doesn't compile" (I'd have to put code pieces into files, invoke the compiler from unit tests, check the output for errors ... not pretty). So how can I test easily that the code fails as it should when callers ignore #Nonnull?
Hiding null within a method does the trick:
public void foo(#NonNull String bar) {
Objects.requireNonNull(bar);
}
/** Trick the Java flow analysis to allow passing <code>null</code>
* for #Nonnull parameters.
*/
#SuppressWarnings("null")
public static <T> T giveNull() {
return null;
}
#Test(expected = NullPointerException.class)
public void testFoo() {
foo(giveNull());
}
The above compiles fine (and yes, double-checked - when using foo(null) my IDE gives me a compile error - so "null checking" is enabled).
In contrast to the solution given via comments, the above has the nice side effect to work for any kind of parameter type (but might probably require Java8 to get the type inference correct always).
And yes, the test passes (as written above), and fails when commenting out the Objects.requireNonNull() line.
Why not just use plain old reflection?
try {
YourClass.getMethod("foo", String.class).invoke(someInstance, null);
fail("Expected InvocationException with nested NPE");
} catch(InvocationException e) {
if (e.getCause() instanceof NullPointerException) {
return; // success
}
throw e; // let the test fail
}
Note that this can break unexpectedly when refactoring (you rename the method, change the order of method parameters, move method to new type).
Using assertThrows from Jupiter assertions I was able to test this:
public MethodName(#NonNull final param1 dao) {....
assertThrows(IllegalArgumentException.class, () -> new MethodName(null));
Here design by contract comes to picture. You can not provide null value parameter to a method annotated with notNull argument.
You can use a field which you initialize and then set to null in a set up method:
private String nullValue = ""; // set to null in clearNullValue()
#Before
public void clearNullValue() {
nullValue = null;
}
#Test(expected = NullPointerException.class)
public void test() {
T inst = ...
inst.foo(nullValue);
}
As in GhostCat's answer, the compiler is unable to know whether and when clearNullValue() is called and has to assume that the field is not null.

Could this call to getString actually return null?

I've updated Android Studio to the latest version, 1.2. I've also recently updated other components like the Android Gradle Extensions.
Now I'm getting warned on methods that I had previously annotated as NotNull. The warning is: Expression might evaluate to null but is returned by the method declared as #NotNull
Here's an example:
public class MyApplication extends Application {
private static SharedPreferences sPrefs = null;
/**
* Corresponds to a string value.
*
* #see #setDeviceInfo(String, String, String)
*/
private static final String PREF_DEVICE_INFO_DEVICE_ADDRESS = "deviceaddress";
#Override
public void onCreate() {
super.onCreate();
sPrefs = PreferenceManager.getDefaultSharedPreferences(this);
}
#NonNull
public static String getDeviceAddress() {
return sPrefs.getString(PREF_DEVICE_INFO_DEVICE_ADDRESS, "");
}
}
I would think that there is no way for getString to return null in this case because I have have set a default value, ""
And even when I look at the implementation of getString (in API 22 anyway) it would seem that this is a case where android studio has simply ignored the fact that my default value is not null and made a false assumption that the default value could be null.
API 22 implementation:
public String getString(String key, String defValue) {
synchronized (this) {
awaitLoadedLocked();
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
Still I need the community to put me at ease or point out what I'm missing before I move on.
You are Safe
You are indeed safe.
You're specifying a default value, and the method cannot return a null value (except if you specify it as your defValue).
Why the Warning Then??
For a number of reasons, IntelliJ/AndroidStudio was just unable to determine the escape route and to figure out your method usage was safe. And the method contracts doesn't formally reject null values for the defValue.
Also, you annotate your method as #NotNull but getString itself isn't annotated (and these are not necessarily runtime checks).
Finally, I wonder if you didn't mistakenly switch your annotations between #NotNull and #NonNull, and consequently switched the implementation provider for your annotation checking. You mention #NotNull in your error and your description, but the code uses #NonNull. They don't behave identically. IntelliJ's NonNull, for instance, is a static-only check.
See Which #NotNull Java annotation should I use? for a nice summary.
Other Possible Issues
Bringing these up just in case...
Possible NPE on getString for a null key
However, if you specify a null key, you could get a NullPointerException thrown by the Map. But that depends on the map implementation used and if that map doesn't allow null keys (I haven't looked into it), and that's not an issue for you (at least not in the code snippet you provided).
As SharedPreferences doesn't specify in its contract anything about the implementation, should just trust what the JDK's Map.get() documentation states:
NullPointerException - if the specified key is null and this map does not permit null keys (optional)
Possible ClassCastException
Beware as well that the SharedPreferences.getString documentation warns you could get a ClassCastException if the stored preference isn't of type String (I suppose unlikely in your case, but I'm mentioning it just in case):
Throws ClassCastException if there is a preference with this name that is not a String.

Why PMD basic rulesets does not capture null dereference?

I am using PMD Plug-in 3.2.6.v2009033006 . But the default rulesets in pmd is not captured possible null pointer exception .
Java Code
public class SignUp extends HttpServlet{
public void doGet(HttpServletRequest req , HttpServletResponse res){
String user = req.getParameter("user");
user.trim();
}
}
user.trim(); if the user variable is null it will be prone to null pointer exception . I checked my code with pmd but it will not indicate this ?
How can i capture this ? . Is there any custom pmd ruleset is available?
Is there any custom rulesets available for capturing this ?
PMD isn't the right tool for this. You should use FindBugs to catch such problems.
But even with FindBugs, you won't catch anything because the above code is perfectly reasonable, and doesn't have any bug, unless you know that getParameter("user") can return null, and that there is something better to do than throwing a NullPointerException in this case.
If such code triggered an error, basically every line of code which calls a method on an object returned by another method would trigger an error. FindBugs supports annotations that allows declaring that the caller of a method should always check for null on the result returned by this method. See http://findbugs.sourceforge.net/manual/annotations.html. But of course, for third-party code, you can't do anything (other than writing your own rules).

Categories

Resources