写点什么

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:009348

评论

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

重复对象:媲美Figma旋转复制,让UI设计更出彩!

职场工具箱

效率工具 设计师 figma ui设计 在线设计工具

让GPU更轻盈 让推理更流畅|焱融YRCache双异步技术激活AI新价值

焱融科技

AI 大模型 推理模型 KVCache

什么是UDFScript用户自定义脚本

天翼云开发者社区

CDN

鸿蒙应用开发从入门到实战(十五):线性布局案例

程序员潘Sir

鸿蒙 HarmonyOS

大数据-107 Flink Apache Flink 入门全解:流批一体的实时计算引擎 从起源到技术特点的全面解析

武子康

Java 大数据 flink spark 分布式

AI 英语口语 APP 开发费用

北京木奇科技有限公司

软件外包公司 AI英语学习

WPS 365联手小米芯片:守护百万研发文档安全,评审效率提速77%

极客天地

一种CDN动态加速首次访问加速方法

天翼云开发者社区

CDN

Parameter ‘**‘ not found. Available parameters are [0, 1, param1, param2]解决办法

刘大猫

人工智能 云计算 大数据 算法 物联网

告别复杂代码!用Dify+Bright Data,可视化搭建高可靠AI数据抓取流水线

阿Q说代码

工作流 dify 亮数据

哈尔滨等保测评:核心知识与实践要点

等保测评

局域网聊天工具,一体化安全办公轻松管理

BeeWorks

即时通讯 IM 私有化部署

GPU 网络通信基础,Part 1(横向与纵向扩展;训练中的通信环节...)

Baihai IDP

AI gpu LLM GPU网络通信

云栖2025 | 人工智能平台 PAI 年度发布

阿里云大数据AI技术

人工智能 阿里云 云栖大会 PAI

观测云产品更新 | 安全监测、监控器、管理、异常追踪、查看器等

观测云

产品迭代

智慧化商品运营:数据科学与人类创意的完美融合

第七在线

精彩抢先看!博睿数据将亮相第二十七届GOPS 全球运维大会上海站 !

博睿数据

区块链Web3系统的开发费用

北京木奇科技有限公司

区块链开发 软件外包公司 web3开发

如何使用极限网关实现 Elasticsearch 集群迁移至 Easysearch

极限实验室

elasticsearch Gateway 数据迁移 极限网关 easysearch

黑龙江二级等保:助力区域网络安全水平整体提升

等保测评

借助人工智能提升工作效率,打造自己的智能体工作流

测试人

城市一张网,以数据之桥擎托未来

脑极体

AI

天润融通ZENAVA重磅发布:让AI成为客服和营销的核心生产力

天润融通

代码生成之外,AI 提效研发的“最短路径”在哪里?|DevChat Tester 产品手记

思码逸研发效能

研发效能 API测试 智能测试 API测试工具 思码逸

HSV - RGB 来点实际的

Miracle

“他她它”深度体验:京东的“万能”工具箱,装进一个有趣的“灵魂”

Alter

出海社交 AI助手

基于 eBPF 技术打造的 LightAPM 应用监控,效果如何

乘云数字DataBuff

监控 ebpf LightAPM

新闻速递丨Altair 与美国威奇托州立大学国家航空航天研究所签署战略备忘录,加速航空航天领域创新步伐

Altair RapidMiner

数字孪生 仿真 CAE hyperworks 航空航天

哈尔滨等保测评:新兴技术适配下的安全升级

等保测评

博睿数据受邀出席东盟人工智能应用生态交流会,以“AI+可观测性”驱动数字化运维模式创新!

博睿数据

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