静态分析代码质量开发工具【免费下载链接】inferA static analyzer for Java, C, C, and Objective-C项目地址https://gitcode.com/gh_mirrors/infer/infer点击查看免费下载本篇技术指南讲解 Meta 开源静态分析器 InferJava、C、C 与 Objective-C 的静态分析工具中内置的Fragment Retains View检查器对应 Issue 类型CHECKERS_FRAGMENT_RETAINS_VIEW。该检查器专门针对 Android 应用用于在Fragment进入不可达状态之前检测其是否未在onDestroyView中显式置空nullify声明的 View 类型字段从而帮助开发者提前发现由 Fragment 视图生命周期管理不当引发的内存泄漏隐患。读完本文你将掌握该检查器的检测原理、激活与配置方法包括--fragment-retains-view与--android-view-class-list参数并能结合源码与测试用例在真实项目中定位和修复此类问题。检查器解决什么问题在 Android 中Fragment的视图View生命周期独立于 Fragment 本身。最佳实践是在onCreateView中初始化所有 View 字段并在onDestroyView中将其置空赋值为null。如果 Fragment 被添加到返回栈back stack中其视图会被销毁但 Fragment 实例仍然存活此时若 Fragment 仍持有对 View 字段的强引用就等于保留了一个“大概率已死”的 View 对象该引用只有在 Fragment 恢复或销毁时才会被清理从而造成内存泄漏。正如该检查器的 Issue 文档 CHECKERS_FRAGMENT_RETAINS_VIEW.md 所述This error type is Android-specific. It fires when aFragmenttype fails to nullify one or more of its declaredViewfields inonDestroyView. In performance-sensitive applications, aFragmentshould initialize allViews inonCreateViewand nullify them inonDestroyView.Fragment Retains View 检查器正是在编译期静态地扫描 Java 代码找出这些漏掉置空操作的 View 字段将运行时才暴露的内存问题提前到分析阶段暴露。支持的平台与语言根据版本 1.3.0 文档checker-fragment-retains-view.md中的语言支持矩阵该检查器只支持 Java语言支持情况C / C / ObjC否C# / .NET否Erlang否Hack否Java是Python否Rust否Swift否这一点与源码一致检查器回调在 registerCheckers.ml 中被注册为(intraprocedural FragmentRetainsViewChecker.callback_fragment_retains_view, Java)即只挂接 Java 语言的过程内分析intraprocedural回调不涉及跨过程调用。激活方式默认开启与手动控制该检查器是 Infer 的**默认检查器default checkers**之一。从 infer.txt 手册 可以看到执行--no-default-checkers会同时停用--static-constructor-stall-checker、--fragment-retains-view、--inefficient-keyset-iterator、--liveness、--parameter-not-null-checked、--pulse、--racerd、--self-in-block、--starvation、--swift-objc-nullability这一组默认检查器。因此在默认配置下无需任何额外参数即可运行。如果需要显式控制Infer 提供以下命令行开关详见 infer.txt--fragment-retains-view激活该检查器与默认行为一致作为--no-fragment-retains-view的反向开关--no-fragment-retains-view停用该检查器--fragment-retains-view-only仅启用 fragment-retains-view 并停用其他所有检查器适合在 CI 或调试中单独聚焦该类问题时使用。典型用法假设已经过 capture 步骤infer analyze --fragment-retains-view-only或者直接使用infer run一步完成捕获与分析infer run -- javac -cp android.jar YourFragment.java注意--fragment-retains-view等检查器开关作用于infer analyze阶段对应的infer capture产物可复用。版本 1.3.0 对应命令行为以当前仓库 infer.txt 手册页为准。检测原理源码级剖析该检查器的核心实现位于 fragmentRetainsViewChecker.ml。整体逻辑可以概括为三条主线1. 只关注onDestroyView回调首先判断当前分析方法是否为 Java 方法然后检查方法名是否等于onDestroyView常量定义于 fragmentRetainsViewChecker.mlis_on_destroy_view判断见 L70。只有onDestroyView方法体才会被进一步分析其他方法直接跳过。2. 识别 Fragment 类及其 View 字段通过Tenv.lookup取得当前类的类型环境后需要同时满足两个条件才会继续见 fragmentRetainsViewChecker.ml类必须是 FragmentAndroidFramework.is_fragment判断该类是否为以下三个 Fragment 类型的子类型见 AndroidFramework.mlandroidx.fragment.app.Fragmentandroid.app.Fragmentandroid.support.v4.app.Fragment字段必须是 View 类型fld_typ_is_view通过AndroidFramework.is_view判断字段类型是否为 View见 AndroidFramework.ml并且要求字段由当前 Fragment 类自身声明is_declared_view_typL79-L82避免对继承来的字段重复误报。is_view的判定并非写死为单一类型而是依赖配置项Config.android_view_class_list一个类只要拥有匹配列表中任一类的父类型即被视为 View见 Config.ml。该列表默认值为[android.view.View]因此android.view.View、android.view.ViewGroup、ListView等子类都会命中。3. 检查字段是否被置空对 Fragment 中每个 View 字段检查器调用PatternMatch.get_fields_nullified定义于 PatternMatch.ml获取在当前onDestroyView中被赋值为null字面量的实例字段集合。该函数遍历过程的中间表示指令Sil.Store寻找形如this.fld null的赋值指令并要求左操作数对象是this通过Exp.is_null_literal rhs与this_ids追踪实现。随后在 fragmentRetainsViewChecker.ml 中对每个声明的 View 字段进行判定若字段既不在置空集合中也没有AutoCleanup注解Annotations.ia_ends_with ia Annotations.auto_cleanup其中auto_cleanup AutoCleanup定义于 annotations.ml则报告一条CHECKERS_FRAGMENT_RETAINS_VIEW警告。也就是说被标注为“自动清理”的字段可以豁免检查。从源码结构看该实现还有一些已知的待办事项TODO见 L68-L69尚未对“Fragment 定义了 View 字段却没有定义onDestroyView”以及“字段在同文件的其他 callee 中被置空”的情形告警。报告格式与自动修复建议触发时检查器会输出形如下面的描述生成逻辑见 fragmentRetainsViewChecker.mlFragment类名does not nullify View field字段名(type类型) in方法名. If this Fragment is placed on the back stack, a reference to this (probably dead) View will be retained.同时附带修复建议In general, it is a good idea to initialize Views inonCreateView, then nullify them inonDestroyView. Note that you also need to make sure they are not being used afterwards.值得注意的是该检查器还支持autofix自动修复报告对象中包含一段补丁文本\n 字段名 null;对于.java源文件会补上分号插入位置是onDestroyView中super调用之后的一行见 fragmentRetainsViewChecker.ml。这意味着在支持 autofix 的 IDE/工作流中可以一键生成置空语句但正如建议所强调的仍需人工确认字段之后不再被使用。该 Issue 类型在 IssueType.ml 中注册ID 为CHECKERS_FRAGMENT_RETAINS_VIEW人类可读名称为 “Fragment Retains View”严重级别为Warning归类于ResourceLeak资源泄漏类别并关联了用户文档infer/documentation/issues/CHECKERS_FRAGMENT_RETAINS_VIEW.md。扩展 View 判定范围--android-view-class-listAndroid 生态中存在大量包装wrapperView 的自定义类它们并不继承android.view.View但同样会长期持有 View 引用。为了覆盖这类场景Infer 提供了命令行参数infer analyze --android-view-class-list com.example.ReallyCustomStub该参数定义于 Config.ml说明为A class C is considered a view when it has a supertype that matches one of these classes. The default is[android.view.View].它是一个字符串列表参数可多次传入值为类的全限定名凡是“拥有匹配该列表中任一类的父类型”的类都会被is_view判定为 View。实战验证官方测试用例仓库中自带了完整的端到端测试位于infer/tests/codetoanalyze/java/fragment-retains-view/目录包含示例源码、预期输出与构建文件可作为理解检查器行为的“活的文档”。测试示例FragmentRetainsViewExample.java 定义了一个继承android.support.v4.app.Fragment的类声明了四个 View 类型字段View mView; ViewGroup mViewSubclass; // View 的子类 CustomView mCustomView; // 继承 ListView 的自定义 View ReallyCustomStubView mReallyCustomView; // 包装 View 的非 View 类在onCreateView中初始化这四个字段而onDestroyView为空实现“not nulling out anything”因此四个字段全部触发告警。测试文件中的注释还专门解释了引入ReallyCustomStub的用意Sometimes people implement a wrapper around a View without implementing the same interface. For the purposes of memory leaks, though, we want to catch such cases too.这正是--android-view-class-list参数存在的意义。预期输出issues.exp 中记录了 4 条CHECKERS_FRAGMENT_RETAINS_VIEW警告每条对应一个字段并带有 autofix 信息例如\n mView null;43:1即建议在第 43 行插入mView null;mViewmViewSubclassmCustomViewmReallyCustomView注意ReallyCustomStub本身不继承任何 View 类若不加配置绝不会被识别为 View而测试之所以能对它告警正是因为测试构建配置显式传入了该参数。构建配置Makefile 展示了该检查器的完整命令行用法可直接作为 CI 配置参考INFER_OPTIONS --debug-exceptions --fragment-retains-view-only --android-view-class-list codetoanalyze.java.checkers.ReallyCustomStub INFERPRINT_OPTIONS \ --issues-tests-fields file,procedure,line_offset,bug_type,bucket,severity,bug_trace,taint_extra,transitive_callees_extra,autofix \ --issues-tests这里--fragment-retains-view-only保证只有本检查器参与分析--android-view-class-list把包装类ReallyCustomStub纳入 View 判定--issues-tests系列选项则输出含autofix字段的格式化结果用于与.exp文件比对。修复建议与最佳实践当报告命中时推荐的修复方式与检查器给出的建议一致在onCreateView中初始化所有 View 字段在onDestroyView中将它们逐一置空field null;确保这些字段在置空之后不再被访问例如异步回调、Handler等路径若字段由某个统一机制自动清理例如自定义注解标注了AutoCleanup检查器会自动豁免否则需显式置空。从工程角度看该检查器最适合作为 Android 项目 CI 流水线的一部分长期开启它属于默认检查器无需额外接入成本且能在每次提交时以极低成本扫描整个代码库防止开发者新引入的 Fragment View 泄漏在回归测试中溜走。小结Fragment Retains View 是 Infer 中一个聚焦、精准的 Android 专项检查器它只分析 Java 代码只关心 Fragment 的onDestroyView只报告“该置空而未置空”的 View 字段并附送 autofix 补丁。其背后是一套清晰的过程内数据流判定this.fld null赋值收集同时通过--android-view-class-list提供了对自定义 View 包装类的可扩展识别能力。对于性能敏感、对内存占用有严格要求的 Android 应用这个检查器是成本极低、收益明确的内存泄漏防线。如需进一步了解可继续阅读检查器实现 fragmentRetainsViewChecker.ml、Issue 类型注册 IssueType.ml、View/Fragment 判定逻辑 AndroidFramework.ml、参数定义 Config.ml以及完整测试样例infer/tests/codetoanalyze/java/fragment-retains-view/。赞分享静态分析代码质量开发工具【免费下载链接】inferA static analyzer for Java, C, C, and Objective-C项目地址https://gitcode.com/gh_mirrors/infer/infer点击查看免费下载相关推荐D3KeyHelper暗黑3终极技能连点器5步打造完美自动化体验D3KeyHelper暗黑3终极技能连点器5步打造完美自动化体验 还在为暗黑破坏神3中重复的技能按键而手指酸痛吗D3KeyHelper作为一款完全免费的暗静态分析代码质量开发工具Infer 静态分析实战用 CHECKERS_FRAGMENT_RETAINS_VIEW 检测 Android Fragment 的 View 引用泄漏Infer 静态分析实战用 CHECKERS_FRAGMENT_RETAINS_VIEW 检测 Android Fragment 的 View 引用泄漏 本篇静态分析代码质量开发工具CANN元数据定义库API文档GetListListFloata nameZH CN_TOPIC_0000002042526998 /a 函数功能a namezh cn_to人工智能CANNAscend上一篇Pyright 静态类型入门类型声明、可赋值性、泛型不变性与 reveal_type 调试下一篇Naive UI 旧版栅格Legacy Grid完全指南NRow / NCol 的 24 栅格布局实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
