Data+AI时代,如何打造下一代数智平台? 了解详情
写点什么

Error Prone 通过检测常见错误帮助改善 Java 代码

  • 2022-10-26
    北京
  • 本文字数:3718 字

    阅读完需:约 12 分钟

Error Prone 通过检测常见错误帮助改善Java代码

Error Prone是谷歌开源的一个 Java 编译插件,可以在编译时进行静态分析、bug 检测,或者对可能的优化提出建议。插件中包括了超过 500 个预定义的bug检查,并且允许第三方和自定义插件。检查到问题之后,Error Prone 能够将问题通过 warning 显示出来或者用预定义的解决方案自动修改代码。Error Prone 支持 Java 8、11,以及 17,可以被用来修复 bug 或者大规模重构。文档中提供了使用 Maven、Bazel、Ant 以及 Grandle 的安装和配置教程。需要将 Error Prone 在编译器中配置为 annotation processor(注解处理器),下面是通过 Maven 创建测试工程的示例:

<plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-compiler-plugin</artifactId>    <version>3.10.1</version>    <configuration>        <release>17</release>        <encoding>UTF-8</encoding>        <compilerArgs>            <arg>-XDcompilePolicy=simple</arg>            <arg>-Xplugin:ErrorProne</arg>        </compilerArgs>        <annotationProcessorPaths>            <path>                <groupId>com.google.errorprone</groupId>                <artifactId>error_prone_core</artifactId>                <version>2.15.0</version>            </path>        </annotationProcessorPaths>    </configuration></plugin>
复制代码


接下来可以创建一个示例类。下面的方法使用了 equals 方法来对比两个数组,更准确地说,此处所比较的是对象本身而不是数组的内容。


public boolean compare(String firstList[], String secondList[]) {    return firstList.equals(secondList);}
复制代码


执行 mvn clean verify 触发 Error Prone 分析,下面是运行结果中的错误信息中:


[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.10.1:        compile (default-compile) on project ErrorProne: Compilation failure[ERROR] …/ErrorProne/src/main/java/org/example/Main.java:[5,28]     [ArrayEquals] Reference equality used to compare arrays[ERROR]   (see https://errorprone.info/bugpattern/ArrayEquals)[ERROR]   Did you mean 'return Arrays.equals(firstList, secondList);'?
复制代码


报出了ArrayEquals错误,Error Prone 的建议是修改实现方式,以比较数组的内容而不是比较对象。


return Arrays.equals(firstList, secondList);
复制代码


报错不仅可以帮助改善代码,也可以让 Error Prone 自动应用解决方案。 -XepPatchChecks 参数的应用应该包含由逗号分隔开的 bug 模式列表,在上面的情况中,只有 ArrayEquals 解决方案用于这段代码。 -XepPatchLocation 参数用于具体定位解决方案文件位置,在当前情境中是修改了源文件:


<compilerArgs>    <arg>-XDcompilePolicy=simple</arg>    <arg>-Xplugin:ErrorProne -XepPatchChecks:ArrayEquals            -XepPatchLocation:IN_PLACE</arg></compilerArgs>
复制代码


现在,在执行 mvn clean verify 之后,类文件被自动修改为:


public boolean compare(String firstList[], String secondList[]) {    return Arrays.equals(firstList, secondList);}
复制代码


文档里提供了更多关于命令行标识的信息。除了内置的 bug 模式,也可以使用例如SLF4J等第三方发布的插件,或创建自定义插件。内置规则的源码提供了多种可用于定义插件的不同示例模板。例如,自定义一个能够用新的 JUnit 5 @BeforeEach 注解器代替旧版 @Before JUnit 注解器的 Error Prone 插件。


和前文例子不同,自定义的 Error Prone 插件应该被放置于 Maven 模块。Error Prone 通过服务加载器机制来加载 bug 检测。这类之际通常一定的配置,然而谷歌的AutoService项目借助 @AutoService 注解简化了配置工作。@BugPattern 注解用于定义 bug 的名称、简介以及严重性。在下面的例子中,如果没有找到 @Before 注解器会返回Description.NO_MATCH ,否则SuggestedFix会用 @BeforeEach 注解替代 @Before 注解。


@AutoService(BugChecker.class)@BugPattern(    name = "BeforeCheck",    summary = "JUnit 4's @Before is replaced by JUnit 5's @BeforeEach",    severity = BugPattern.SeverityLevel.SUGGESTION)public class BeforeCheck extends BugChecker implements BugChecker.AnnotationTreeMatcher {    private static final Matcher<AnnotationTree> matcher =            isType("org.junit.Before");
@Override public Description matchAnnotation(AnnotationTree annotationTree, VisitorState visitorState) { if (!matcher.matches(annotationTree, visitorState)) { return Description.NO_MATCH; } return describeMatch(annotationTree, SuggestedFix.replace(annotationTree, "@BeforeEach")); }}
复制代码


构建自定义 Error Prone 插件的时候都是需要 Error Prone 和 AutoService 依赖的。


<dependency>  <groupId>com.google.errorprone</groupId>  <artifactId>error_prone_annotations</artifactId>  <version>2.15.0</version></dependency><dependency>  <groupId>com.google.errorprone</groupId>  <artifactId>error_prone_check_api</artifactId>  <version>2.15.0</version></dependency><dependency>  <groupId>com.google.auto.service</groupId>  <artifactId>auto-service-annotations</artifactId>  <version>1.0.1</version></dependency>
复制代码


AutoService 应该被配置为一个注解处理器。


<annotationProcessorPaths>    <path>        <groupId>com.google.auto.service</groupId>        <artifactId>auto-service</artifactId>        <version>1.0.1</version>    </path></annotationProcessorPaths>
复制代码


现在,自定义的 Error Prone 插件可以通过 mvn install 命令,安装在本地的 Maven 仓库。执行命令后,示例工程应该会被配置为使用新的自定义插件作为注解处理器。


<annotationProcessorPaths>    <path>        <groupId>org.example.custom.plugin</groupId>        <artifactId>ErrorProneBeforeCheck</artifactId>        <version>1.0-SNAPSHOT</version>    </path></annotationProcessorPaths>
复制代码


新的 BeforeCheck 应该被加入到了 Error Prone 分析中。


<compilerArgs>  <arg>-XDcompilePolicy=simple</arg>  <arg>-Xplugin:ErrorProne -XepPatchChecks:BeforeCheck            -XepPatchLocation:IN_PLACE</arg></compilerArgs>
复制代码


添加一个示例测试类,其中包含@Before@BeforeEach的两个注解。


public class ErrorProneTest {  @Before  void before() {  }  @BeforeEach  void beforeEach() {  }}
复制代码


运行 mvn verify 时,新的自定义 Error Prone 插件将用@BeforeEach注解替换@Before注解。


public class ErrorProneTest {  @BeforeEach  void before() {  }  @BeforeEach  void beforeEach() {  }}
复制代码


Error Prone 所使用的 Java internal 目前处于隐藏状态,可能会导致如下错误:


java.lang.IllegalAccessError: class com.google.errorprone.BaseErrorProneJavaCompiler (in unnamed module @0x1a6cf771) cannot access class com.sun.tools.javac.api.BasicJavacTask (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.api to unnamed module @0x1a6cf771
复制代码


Maven 的解决办法是通过在项目根目录下创建.mvn 目录来暴露 Java internal,在目录中创建一个 jvm.config 文件,其中配置如下:


--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED--add-exports jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED--add-exports jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED--add-opens jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED--add-opens jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
复制代码


或者可以将--add-exports--add-opens 参数配置添加到 Maven 编译器插件的 pom 文件中:


<plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-compiler-plugin</artifactId>    <version>3.10.1</version>    <configuration>        <compilerArgs>            <arg>--add-exports</arg>            <arg>jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
复制代码


更多在 Bazel、Ant 和 Gradle 中使用 Error Prone 的信息可参见安装引导


相关阅读:

Java 近期新闻:顺序集合、Spring 6.0-RC1、Tomcat、Reactor 2022.0-RC1

Spring Boot 3 将于 2022 年 11 月发布,延迟了对 Java 模块系统的支持


2022-10-26 08:008890

评论

发布
暂无评论
发现更多内容

软件测试/测试开发/全日制/测试管理丨Appium Inspector

测试人

软件测试

【年后跳槽必看篇-非广告】老生常态之Spring AOP/IOC 实现原理

派大星

Java 面试 跳槽

苹果电脑重装系统教程

Rose

苹果电脑Mac教程:如何开启任何来源选项

Rose

解决苹果无线鼠标、键盘或触控板无法被 Mac 识别的方法

Rose

苹果电脑应用程序无法打开提示不明开发者或文件损坏的处理方法

Rose

AI遇上传统文化,文心一言上央视带来跨时空访古体验

飞桨PaddlePaddle

人工智能 深度学习

让 K8s 更简单!8款你不得不知的 AI 工具-Part 1

SEAL安全

开源 AI Kubernetes

替代关系型数据库 MAX 聚合函数的思路

alexgaoyh

MySQL 替代 聚合函数 最新数据 自关联

eBPF运行时安全

统信软件

安全 ebpf 运行时

从前端角度浅谈性能 | 京东物流技术团队

京东科技开发者

​万界星空科技MES系统如何进行产品的质量管理

万界星空科技

质量管理 MES系统 制造业 mes 制造业生产管理系统

2024年的第一场 MatrixOne Meetup 来啦!

MatrixOrigin

数据库 分布式 云原生 MatrixOrigin MatrixOne

QCN9024: The future of wireless communications, five major advantages over competitors

wallysSK

堡垒机和数据库防水坝的区别一二

行云管家

数据库 网络安全 堡垒机 数据库防水坝

LED透明显示屏前景发展怎么样?

Dylan

LED显示屏 全彩LED显示屏 led显示屏厂家 市场 #研发

“无法打开应用,因为Apple无法检查其是否包含恶意软件“解决方法

Rose

FCPX 插件无法使用?|Final Cut Pro X 插件不能使用出现叹号的解决办法

Rose

数据采集在制造业中的应用场景

万界星空科技

数据采集 MES系统 设备管理 万界星空科技 生产管理

App加固:不同类型和费用对比

Acrobat Pro DC 2023如何插入附件?Acrobat Pro DC添加附件方法

Rose

如何自定义Safari的起始页

Rose

运行Adobe应用提示非正版This non-genuine Adobe app has been disabled soon如何解决

Rose

adobe

精彩推荐 |【Java技术专题】「重塑技术功底」攻破Java技术盲点之剖析动态代理的实现原理和开发指南(中)

码界西柚

Java 后端开发 JDK 动态代理 CGLIB 动态代理 2024年第十一篇文章

云厂商是什么意思?2024年知名云厂商有哪些?

行云管家

云计算 云服务 行云管家 云厂商

云联接:揭开SD-WAN神秘面纱,颠覆你对网络的认知!

博文视点Broadview

Parallels Desktop 17 安装Windows 11 教程 附激活工具

Rose

复杂经济时期下的企业财务规划战略

智达方通

全面预算 情景规划 企业财务规划 财务规划

喜讯!矩阵起源子公司通过“国家高新技术企业”认定,引领数据库行业科技创新!

MatrixOrigin

数据库 分布式 云原生 MatrixOrigin MatrixOne

NFTScan | 01.08~01.14 NFT 市场热点汇总

NFT Research

NFT NFT\ NFTScan

第三方 Cookie 被禁用?企业该如何实现用户精准运营和管理

Authing

Cookie Authing 用户运营

Error Prone 通过检测常见错误帮助改善Java代码_编程语言_Johan Janssen_InfoQ精选文章