Infer 静态分析之 CHECKERS_CALLS_EXPENSIVE_METHOD:用 @PerformanceCritical 与 @Expensive 守卫关键路径性能
静态分析代码质量开发工具【免费下载链接】inferA static analyzer for Java, C, C, and Objective-C项目地址https://gitcode.com/gh_mirrors/infer/infer点击查看免费下载导读CHECKERS_CALLS_EXPENSIVE_METHOD是 Facebook 开源静态分析器 Infer 中 Annotation Reachability注解可达性检查器内置的一类性能回归问题。当代码中被标记为PerformanceCritical的方法直接或间接调用了被标记为Expensive的方法时Infer 会以该问题类型向开发者报告从而在 CI 阶段提前拦截「高性能关键路径上误调昂贵操作」的回归。读完本文你将掌握该问题的完整语义、触发规则、注解用法、相关命令行开关以及如何通过仓库内的真实测试用例验证分析行为。问题定义一条不可触碰的性能红线依据 CHECKERS_CALLS_EXPENSIVE_METHOD.md 中的定义A method annotated withPerformanceCriticaltransitively calls a method annotatedExpensive.即被PerformanceCritical注解的方法以传递transitive方式调用了被Expensive注解的方法。这里的「传递」是关键——调用链中间可以隔着多层普通方法只要最终能到达一个Expensive方法就会被报告。原文档给出的最小触发示例class C { PerformanceCritical void perfCritical() { expensive(); } Expensive void expensive() {} }在该示例中perfCritical()被标记为性能关键路径它直接调用了expensive()因此 Infer 产生一条CHECKERS_CALLS_EXPENSIVE_METHOD报告并在问题轨迹trace中标明「source 为 PerformanceCriticalsink 为 Expensive」。该问题类型的注册位置该问题类型在 Infer 源码中注册于 IssueType.mlregister ~category:PerfRegression ~id:CHECKERS_CALLS_EXPENSIVE_METHOD ... ~user_documentation:[%blob ./documentation/issues/CHECKERS_CALLS_EXPENSIVE_METHOD.md]从源码可以确认两点其一它属于PerfRegression性能回归类别其二本文所讲解的这份文档正是 Infer 在生成问题报告时直接嵌入的用户文档user_documentation也就是说你在命令行或 IDE 中看到的问题说明正文就来源于仓库中的这份 Markdown。两个核心注解PerformanceCritical 与 ExpensivePerformanceCritical声明「这条路径不容有失」源码位于 annotations/src/main/java/com/facebook/infer/annotation/PerformanceCritical.javapackage com.facebook.infer.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; Retention(RetentionPolicy.CLASS) Target(value {ElementType.METHOD, ElementType.TYPE}) public interface PerformanceCritical {}关键信息可标注在方法与类型类/接口两个粒度上。标注在类型上意味着该类以及按规则继承该注解的子类的所有方法都被视为性能关键路径保留策略为CLASS即注解会写入 class 文件但不要求在运行时可见仅供静态分析读取。Expensive声明「这个方法代价高昂」源码位于 annotations/src/main/java/com/facebook/infer/annotation/Expensive.javapackage com.facebook.infer.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; Retention(RetentionPolicy.CLASS) Target({ElementType.METHOD, ElementType.TYPE}) public interface Expensive {}同样的Expensive也支持方法级与类型级标注。将Expensive标注在类上即声明「该类的所有方法都是昂贵的」例如测试用例中的ExpensiveClass。承载检查器Annotation ReachabilityCHECKERS_CALLS_EXPENSIVE_METHOD并非独立运行的检查器而是由Annotation Reachability注解可达性检查器内置的一对「source/sink」规则产出。在 Checker.ml 中检查器的官方说明为Given pairs of source and sink annotations, e.g.AandB, this checker will warn whenever some method annotated withAcalls, directly or indirectly, another method annotated withB. Besides the custom pairs, it is also possible to enable some built-in checks, such asPerformanceCriticalreachingExpensiveorNoAllocationreachingnew.即检查器的设计初衷是处理任意「源注解 → 汇注解」配对PerformanceCritical → Expensive只是其中一个内置检查项。该检查器支持的编程语言包括 Java、C/CClang、Erlang以及实验性的 Swift。注意该检查器默认不启用enabled_by_default false需要在命令行显式开启。如何启用由于该问题由 Annotation Reachability 检查器产出你需要同时启用检查器与内置的 expensive 检查项。从 Config.ml 可以看到--annotation-reachability-expensive check if methods annotated with PerformanceCritical can call expensive methods (annotated Expensive or modeled, with annotation reachability checker)典型运行方式infer run --annotation-reachability-only --annotation-reachability-expensive -- javac Example.java实际命令行前缀以infer analyze --help中--annotation-reachability开头的开关为准开启检查器本身可使用-a annotation-reachability或--annotation-reachability-only。真实触发场景从测试用例看分析行为仓库的测试目录 infer/tests/codetoanalyze/java/annotreach/basic/ 保存了该检查器的大量 Java 测试用例其中 ExpensiveCallExample.java 专门覆盖了CHECKERS_CALLS_EXPENSIVE_METHOD的各种变体期望输出记录在 issues.exp 中。下面按场景逐一解读。场景一直接调用必报PerformanceCritical void directlyCallingExpensiveMethod() { expensiveMethod(); // expensiveMethod 被 Expensive 标注 }期望输出ExpensiveCallExample.directlyCallingExpensiveMethod():void, 1, CHECKERS_CALLS_EXPENSIVE_METHOD, ERROR, [Method ...directlyCallingExpensiveMethod, marked as source PerformanceCritical, calls ...expensiveMethod, ... marked as sink Expensive]场景二间接调用传递可达必报void methodWrapper() { expensiveMethod(); } PerformanceCritical void indirectlyCallingExpensiveMethod() { methodWrapper(); // 中间隔了一层普通方法 }期望输出显示 trace 依次为indirectlyCallingExpensiveMethod → methodWrapper → expensiveMethod印证了「transitively」的语义中间方法不需要任何注解只要调用链最终触达Expensive方法即报。场景三长调用链跨类传递必报PerformanceCritical void longerCallStackToExpensive() { callsExpensive2(); // 本类方法 } void callsExpensive2() { mOther.callsExpensive1(); // Other 类的方法 } // Other 类中 void callsExpensive1() { expensive(); // Expensive }期望输出完整展开为longerCallStackToExpensive → callsExpensive2 → callsExpensive1 → expensive的四层调用轨迹每一层方法都出现在报告 trace 中便于开发者定位插桩点。场景四类型级注解继承必报Expensive class ExpensiveClass { void anExpensiveMethod() {} } PerformanceCritical class PerformanceCriticalClass { void performanceCriticalMethod1(ExpensiveClass c) { c.anExpensiveMethod(); // 类级 Expensive 生效 } }同时子类继承PerformanceCritical类注解后同样受检class PerformanceCriticalSubclass extends PerformanceCriticalClass { void subclassPerformanceCriticalMethod1(ExpensiveClass c) { c.anExpensiveMethod(); // 应报告 } }issues.exp 第 29-31 行确认了这些子类场景均产出该问题。场景五条件分支内的调用按到达次数报告PerformanceCritical void callsExpensiveInConditionalBranch() { if (test()) { expensiveMethod(); } }issues.exp 第 40 行显示该用例报告数量为2即该错误位置出现两次与分支路径展开相关说明检查器按控制流路径展开分析分支内的调用不会被遗漏。场景六内置模型——findViewByIdPerformanceCritical View callsFindViewByIdFromView(ImageView view, int id) { return view.findViewById(id); }issues.exp 第 36-37 行显示android.view.View.findViewById与android.app.Activity.findViewById无需任何注解即被视为Expensive汇点。这正是 Checker.ml 中提到的「modeled建模」机制Infer 为部分已知的高开销系统 API 内置了模型等价于给它们贴上了Expensive。不应报告的反例测试用例同时给出了不应触发的对照PerformanceCritical void notCallingExpensiveMethod() { nonExpensiveMethod(); // 普通方法不报告 } void performanceCriticalMethod4(Other o) { o.inexpensiveMethod(); // 不报告 }这些反例在 issues.exp 中没有对应条目用于防止误报。相关配套开关除--annotation-reachability-expensive外Config.ml 中还提供了多个影响分析行为的开关命令行开关默认值作用--annotation-reachability-apply-superclass-annotationstrue将父类与接口上的注解应用到未被其覆写的方法上--annotation-reachability-check-loopsfalse在 trace 中标高嵌套在循环中的调用点callsite--annotation-reachability-custom-models空用正则表达式将任意方法「视为」带有某注解例如{Annotation: [com\\.Myclass\\.foo.*]}支持allow/block列表--annotation-reachability-custom-pairs空自定义 source/sink以及可选的 sanitizer配对并可通过minimize_sinks默认true与minimize_sources默认false控制路径最小化--annotation-reachability-expensivefalse启用PerformanceCritical → Expensive内置检查--annotation-reachability-no-allocationfalse启用NoAllocation方法不得分配对象的检查--annotation-reachability-report-source-and-sinkfalse报告同时被标记为 source 与 sink 的方法其中与本文最相关的是--annotation-reachability-custom-models当你无法或不想改动第三方库源码时可以用正则把库中的昂贵方法建模为Expensive从而在不添加注解的情况下获得同样的检查能力——这正是 Checker.ml 所述「在没有注解的语言里也能工作」的实现途径。--annotation-reachability-apply-superclass-annotations则解释了测试用例中接口AnnotatedInterface的PerformanceCritical能作用于实现类的行为见 issues.exp 第 39 行annotatedPerformanceCriticalInInterface。与相关问题类型的区分在同一个测试目录中还能看到与之相邻的问题类型CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED当Expensive方法覆写了未标注的父类方法时报告见 ExpensiveSubtypingExample.java 与 issues.exp 第 45 行关注的是「继承关系下的注解缺失」CHECKERS_CALLS_EXPENSIVE_METHOD关注的是「性能关键方法调用昂贵方法」即本文主题。两者一静一动前者检查类层级结构的标注一致性后者检查调用图的性能红线均属于 Annotation Reachability 检查器内置规则。落地实践建议结合上述源码与测试行为在生产项目中落地该检查可以参考以下路径标注关键路径对 UI 渲染、热路径、锁内代码等耗时敏感的方法标注PerformanceCritical方法级或类级标注昂贵操作对网络请求、磁盘 IO、反射、大对象分配等操作标注Expensive若涉及第三方库用--annotation-reachability-custom-models以正则建模接入 CI在构建命令中加入--annotation-reachability-only --annotation-reachability-expensive使任何新引入的「关键路径调用昂贵方法」在合并前即被拦截按需开启 trace 增强需要排查循环内调用时可开启--annotation-reachability-check-loops让问题轨迹中标出位于循环中的调用点。小结CHECKERS_CALLS_EXPENSIVE_METHOD是 Infer Annotation Reachability 检查器的内置性能回归规则语义为「PerformanceCritical方法传递可达Expensive方法」。通过类型级注解、跨类传递调用链、接口继承以及内置 API 模型它在不改动调用方代码的前提下实现跨层级的性能红线守卫。仓库中的 issues.exp 记录了全部期望行为是验证分析器语义的第一手资料结合 Config.ml 中的开关与 Checker.ml 中的检查器说明即可在真实项目中快速落地。赞分享静态分析代码质量开发工具【免费下载链接】inferA static analyzer for Java, C, C, and Objective-C项目地址https://gitcode.com/gh_mirrors/infer/infer点击查看免费下载相关推荐Infer 注解可达性分析Annotation Reachability检测器从 PerformanceCritical 到 Expensive 的调用链追踪Infer 注解可达性分析Annotation Reachability检测器从 PerformanceCritical 到 Expensive 的调静态分析代码质量开发工具Infer 静态分析CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED 错误详解与 Expensive 子类型规则Infer 静态分析CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED 错误详解与 Expensive 子类型规则 导读 本篇静态分析代码质量开发工具CI/CD集成Infer在持续集成中的最佳实践CI/CD集成Infer在持续集成中的最佳实践 本文详细介绍了Facebook开发的静态分析工具Infer在CI/CD环境中的集成方案包括Jenkins和G静态分析代码质量开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

SpringBoot整合Elasticsearch7.2:弃用官方Starter,改用RestHighLevelClient

SpringBoot整合Elasticsearch7.2:弃用官方Starter,改用RestHighLevelClient

简介:面向Java开发者的Spring Boot整合Elasticsearch 7.2.0实战PDF文档,围绕新版搜索引擎接入的常见问题展开。文档首先指出版本对应关系中的坑:Spring Boot 2.1.X自带的spring-boot-starter-data-elasticsearch默认对应Elasticsearch 2.X&am…

2026/9/25 10:33:55 阅读更多 →
华为路由器配置实例:从基础IP到静态路由与VRRP实战指南

华为路由器配置实例:从基础IP到静态路由与VRRP实战指南

简介:华为路由器配置实例文档面向网络工程初学者、HCIA备考者及需要快速上手华为设备配置的运维人员,以R2621路由器和S3026e交换机各一台搭建真实实验环境,完整演示VLAN划分、虚拟网与物理网互通、防火墙策略及ACL访问控制配置。文档以四台PC…

2026/9/25 10:33:55 阅读更多 →
YOLOv5裂缝检测实战:从数据标注到模型部署全流程解析

YOLOv5裂缝检测实战:从数据标注到模型部署全流程解析

简介:这份基于PythonYolov5的路面桥梁裂缝检测识别毕业设计项目,面向计算机相关专业学生和需要项目实战的开发者,可用于毕业设计、课程设计或期末大作业。项目经导师指导并获99分高分评价,代码与模型完整、确保可运行,…

2026/9/25 11:37:51 阅读更多 →

最新新闻

代码阅读工作流实战:用 TaoToken 统一 Key 打通文件搜索、符号跳转与提问策略

代码阅读工作流实战:用 TaoToken 统一 Key 打通文件搜索、符号跳转与提问策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/26 16:40:44 阅读更多 →
5分钟读懂OpenManus配置:TaoToken统一Key接入Multi Agent实战

5分钟读懂OpenManus配置:TaoToken统一Key接入Multi Agent实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/26 16:40:44 阅读更多 →
多酒店预订系统实战:数据隔离、房态同步与三端接入

多酒店预订系统实战:数据隔离、房态同步与三端接入

简介:这是一套面向酒店行业开发者与中小连锁酒店经营者的多酒店预订管理系统源码,覆盖APP、H5与小程序三端,可解决分店扩张、房态同步、会员营销与内部协同等实际业务问题。资源包共2582个文件,约80.13MB,以1428个PHP业…

2026/9/26 16:40:44 阅读更多 →
手势识别打地鼠实战:MediaPipe+OpenCV从摄像头到锤子的完整链路

手势识别打地鼠实战:MediaPipe+OpenCV从摄像头到锤子的完整链路

简介:这是一份面向人机交互课程学习者与OpenCV入门开发者的完整项目资料,围绕手势识别控制的打地鼠游戏展开,可用于课程设计、实验复现与交互方式对比研究。资源包共27个文件,约60.1MB,包含6个Python源码文件、4个XML配…

2026/9/26 16:40:44 阅读更多 →
AiPy 为 openclaw 穿上安全铠甲:skill 随便用也不翻车的 TrustTools 配置骨架

AiPy 为 openclaw 穿上安全铠甲:skill 随便用也不翻车的 TrustTools 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/26 16:40:44 阅读更多 →
20家公司AI面试官吐血总结:3个月速成AI Agent开发,TaoToken统一Key接入Cline与CC Switch配置实战

20家公司AI面试官吐血总结:3个月速成AI Agent开发,TaoToken统一Key接入Cline与CC Switch配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/26 16:39:44 阅读更多 →

日新闻

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、…

2026/9/26 0:00:25 阅读更多 →
学校官网模拟全流程实践:从页面布局到后端接口与部署

学校官网模拟全流程实践:从页面布局到后端接口与部署

如果你正在找一门 Web 大作业的题目,或者刚开始接触 Web 前端开发想做点能拿来展示的东西,“学校官网模拟”几乎是最稳的选择。题目看着简单,但要把导航、新闻列表、轮播 Banner、二级页面、后台数据都串起来,其实已经把前端布局、…

2026/9/26 0:00:25 阅读更多 →
超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

超级玛丽游戏源码C++:从零搭建横版跳跃游戏工程

简介:这是一份面向游戏开发初学者与C进阶学习者的超级玛丽(超级马里奥)游戏源码,基于C面向对象编程实现,适合想通过经典项目理解游戏主循环、角色类设计、地图关卡加载与物理碰撞检测的读者参考。压缩包共49个文件&…

2026/9/26 0:00:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/25 19:27:14 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/25 20:29:09 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/25 20:29:43 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/25 20:29:31 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/25 19:27:26 阅读更多 →