概述

在Caffeine源码里看到checkerframework这个小工具,故有此文:

<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.checkerframework</groupId>
<artifactId>checker-compat-qual</artifactId>
<version>2.5.5</version>
</dependency>

​maven-checker-framework​

介绍

​官网​​​​GitHub​​​​maven​​ The Checker Framework,CF,提供一套机制,可以通过编写插件来扩展Java编译器的功能。内置几十种检查规则,也可以方便的自定义检查规则。主要利用Java中的注解增强编译过程中类型检查步骤的能力。

实例

GetStarted.java源码:

import org.checkerframework.checker.nullness.qual.*;
public class GetStarted {
void sample() {
@NonNull Object ref = null;
}
}

运行时用CF提供的javac编译你需要检测的代码。对于Linux/Mac用户,可在​​.bashrc​​​或​​.zshrc​​里增加这么两行:

export CHECKER_FRAMEWORK=${install_path}/checker-framework-2.1.9
alias javacheck='$CHECKER_FRAMEWORK/checker/bin/javac'


​​​javacheck -processor org.checkerframework.checker.nullness.NullnessChecker GetStarted.java​​​​-process org.checkerframework.checker.nullness.NullnessChecker​​指定需要检测的错误是空指针,CF还自带许多其他有用的插件检测其他类型错误。

上述指令就会打印:

GetStarted.java:5: 错误: [assignment.type.incompatible] incompatible types in assignment.
@NonNull Object ref = null;
^
found : null
required: @UnknownInitialization @NonNull Object
1 个错误

IDEA支持

​checker-framework-support​​ 久未更新。

拓展

RetentionPolicy

@RetentionPolicy.SOURCE =>通常用于文档
@ RetentionPocily.CLASS =>允许向编译器提供一些信息,但不向JVM提供信息(例如,在编译期间执行代码生成)
@ RetentionPolicy.RUNTIME =>允许在JVM级别(因此在运行时)检索注释信息。

FindBugs

FindBugs是一套成熟的 bug 解决方案,有两个实现:​​Google Code​​​以及 ​​Source Forge​​,从下面的两个截图可见,两者包括的依赖库,即artifact,基本相同。

Checker框架学习笔记_java


Checker框架学习笔记_java_02


而 JSR 305,则是FindBugs的一部分。

JSR 305

JCP官网:​​JSR 305​​​,
通过定义注解类,适合在底层通用代码库中使用。GAV如下:

<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>

或者

<dependency>
<groupId>net.sourceforge.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.7</version>
</dependency>

​findbugs-and-jsr-305​

JSR 308

​JSR 308​​,JCP规范。

​checkerframework-jsr308​​实现JSR308,Java 8类型注释,允许类型检查器执行静态代码分析。

JSR 305 vs JSR 308

​jsr305-vs-jsr308​

I can answer your last question. They are not the same thing. 305 is about new annotations where you can already put them, which can help provide programmatic visibility into a design by contract system. So that if a certain method is supposed to not return null, or if a certain method is supposed to never receive a null parameter, it is possible to tell the system analyzing the annotations to look out for this specific case at this piece of code.

308 is about being able to annotate more things, such as a generic parameter and a type cast. I imagine a primary use for that is to be able to suppress warning on a specific type cast, instead of having to declare a local variable for that purpose. The @SuppressWarnings annotation already exists (whereas JSR-305 would look to define new ones), but in JSR-308 it could be applied to more cases.

According to this 308 will be part of Java7, which would imply it is quite well along to being stable. JSR-305 isn’t on the list, so it doesn’t look like it will make it to Java7.

对比

各种项目定义自己的NonNull注释,例如:

  1. org.checkerframework.checker.nullness.qual.NonNull
  2. edu.umd.cs.findbugs.annotations.NonNull
  3. javax.annotation.Nonnull
  4. javax.validation.constraints.NotNull
  5. lombok.NonNull
  6. org.eclipse.jdt.annotation.NonNull

参考

​http://shzhangji.com/cnblogs/2018/09/22/how-to-avoid-null-pointer-exception/​