这是findbugs的错误吗?
Is this a bug of findbugs?
我有一个包含如下代码的 jenkins 插件:
public int getLastBuildNumber() {
if (project != null && project.getLastBuild() != null ) {
return project.getLastBuild().getNumber();
}
return 0;
}
当我使用 mvn release:prepare release:perform -Dusername=myusername -Dpassword=mypassword
发布代码时,我收到一个错误 Possible null pointer dereference
。
这是 mvn findbugs:gui
的结果:
为什么说The return value from a method is dereferenced without a null check
?
我认为 project != null && project.getLastBuild() != null
是空检查,不是吗?
这是findbugs的bug吗?我该如何解决?或者我可以在发布我的 jenkins 插件时禁用 findbugs 吗?
您可以访问 here 获取完整代码。
除非您的 Project
class 是不可变的或者(至少)getLastBuild()
返回的值是一个 final
字段,否则您的空检查是不够的。
这是因为,理论上,其他线程可能会在您的 return
语句之前调用 project.setLastBuild(null)
:
if (project != null && project.getLastBuild() != null) {
// thread T does project.setLastBuild(null) here -- for whatever reason
return project.getLastBuild().getNumber(); // NPE!
}
要做到这一点,您需要远离那些活动部件并制作您自己的本地副本(恕我直言,在这种情况下同步几乎不是一个选项):
LastBuild lastBuild = project != null ? project.getLastBuild() : null; // this only works as long as your project reference is final
return lastBuild != null ? lastBuild.getNumber() : 0;
或者,更好的是,利用 Java8 Optional
一次性执行所有必要的空值检查(隐式地):
return Optional.ofNullable(project)
.map(Project::getLastBuild)
.map(LastBuild::getNumber)
.orElse(0);
我有一个包含如下代码的 jenkins 插件:
public int getLastBuildNumber() {
if (project != null && project.getLastBuild() != null ) {
return project.getLastBuild().getNumber();
}
return 0;
}
当我使用 mvn release:prepare release:perform -Dusername=myusername -Dpassword=mypassword
发布代码时,我收到一个错误 Possible null pointer dereference
。
这是 mvn findbugs:gui
的结果:
为什么说The return value from a method is dereferenced without a null check
?
我认为 project != null && project.getLastBuild() != null
是空检查,不是吗?
这是findbugs的bug吗?我该如何解决?或者我可以在发布我的 jenkins 插件时禁用 findbugs 吗?
您可以访问 here 获取完整代码。
除非您的 Project
class 是不可变的或者(至少)getLastBuild()
返回的值是一个 final
字段,否则您的空检查是不够的。
这是因为,理论上,其他线程可能会在您的 return
语句之前调用 project.setLastBuild(null)
:
if (project != null && project.getLastBuild() != null) {
// thread T does project.setLastBuild(null) here -- for whatever reason
return project.getLastBuild().getNumber(); // NPE!
}
要做到这一点,您需要远离那些活动部件并制作您自己的本地副本(恕我直言,在这种情况下同步几乎不是一个选项):
LastBuild lastBuild = project != null ? project.getLastBuild() : null; // this only works as long as your project reference is final
return lastBuild != null ? lastBuild.getNumber() : 0;
或者,更好的是,利用 Java8 Optional
一次性执行所有必要的空值检查(隐式地):
return Optional.ofNullable(project)
.map(Project::getLastBuild)
.map(LastBuild::getNumber)
.orElse(0);