“对象敏感指针分析以接收者对象的抽象身份区分实例方法的不同分析上下文。它通常在包含式points to约束上增加方法上下文和堆上下文,再与调用图共同迭代。”
形式陈述
静态调用图从程序的调用、分配与方法声明语法中提取哪些调用位置可能执行哪些函数或方法。设
若调用点
可靠性要求:任意允许执行在
本页固定封闭世界、静态类型的单继承面向对象核心:全部类定义已知;无反射、动态装载、native回调;对象来自显式分配;静态初始化和构造器调用已表示成普通可达代码。dispatch(K,f) 表示对象动态类为
两种可执行构造
类层次分析(CHA):对接收者静态类型为 dispatch(K,f) 都列入目标;直接静态调用只加其确定目标。子类型关系提供候选动态类的范围。
快速类型分析(RTA):除可达方法集
- 扫描新可达方法,将其中分配的类加入
,将直接调用的方法加入 - 对所有可达的虚调用点,只考虑
中且满足接收者静态类型约束的类,加入相应目标方法 - 新目标可能暴露新分配,继续直到两个集合和调用边都不变
这是一个最小不动点,不能只扫描入口中的 new 一次。RTA的类集是全程序共享的近似,还没有知道某个具体变量究竟指向哪一个分配。
直觉
CHA问:“按类定义,这个对象有可能是哪类?”RTA再加一条过滤:“从入口可到达的代码,真的有机会造出这个类吗?”后者通常少些边,但类是否会被分配与方法是否可达互相依赖,必须一边发现、一边更新。
这两种方法都不按运行时间排序。即使一个分配语句在调用之后,流不敏感的RTA仍可能用它扩大该调用的候选集。调用图说明潜在调用关系,不是一段运行日志。
例子与边界
新发现的分配会反过来改变旧调用点
类A和子类B都实现方法 f。入口代码为:
main:
x = new B
x.f() // c
B.f:
makeA()
makeA:
y = new A
return y
A.f:
return
假设 x 的静态类型声明为A。CHA从一开始就在调用点
| 发现阶段 | 可达方法中的新信息 | 已分配类 | c的候选目标 |
|---|---|---|---|
| 扫描main | 分配B,遇到虚调用 | ||
| 扫描B.f | 直接调用makeA | 不变 | |
| 扫描makeA | 分配A | 加入A.f | |
| 扫描A.f | 没有新调用或分配 | 稳定 |
实际运行中,x始终指向B,makeA的返回值也没有赋给x。因此A.f仍是一条伪边。RTA可靠地保留了真实B.f,却因为全局类集合而失去变量级区别;指针分析可以继续问“哪个对象能流到x”,从而进一步过滤目标。
若删除B.f中的makeA调用,而makeA又没有其他入口,RTA不会因源码中出现 new A 就加入A。扫描所有方法中的分配而不管可达性,会退化为另一种更粗算法,不能仍用上面的迭代过程解释结果。
继承不等于产生一份新的方法
再增加C继承B,但不重写f。new C使C进入已分配类集后,dispatch(C,f)仍是B.f;图中应加入B.f这条边,而不是虚构一个C.f方法节点。多继承、接口默认方法及语言的派发规则需要相应调整lookup,不能只比较类名字。
开放世界的边界
如果外部插件可以稍后装载D并重写f,封闭世界结果不能直接用于删除该派发分支。可以显式把未知实现建成保守外部目标,或在受控的全程序构建中证明类集已经封闭。反射、JNI与回调也需模型;“分析器没看到”不是不可发生的证据。
推论与应用
CHA可靠性的理由是:真实接收者动态类必须满足其静态类型限制,实际派发方法必在枚举结果里。RTA还需对真实执行归纳:入口可达;每次真实分配所在的方法已可达,因此相应类进入
设方法数为
调用图常用于删除不可达代码、估算递归分量、构造过程间控制流图和安全扫描。但方法级图中的一个环只说明存在潜在递归依赖,不证明每次执行都会递归,也不证明递归无法终止。进一步区分调用和返回,应进入上下文敏感的过程间分析。
参考资料
-
David F. Bacon, Fast and Effective Optimization of Statically Typed Object-Oriented Languages,博士论文1997、技术报告1998:Rapid Type Analysis、类层次与可达分配
-
Anders Møller and Michael I. Schwartzbach, Static Program Analysis,2026年8月版,Chapter 10:函数流信息到调用目标与过程间图
-
Nate Nystrom, Cornell CS711: Interprocedural control-flow analysis, 2005,slides 2–7:调用图、CHA与RTA
-
David Grove and Craig Chambers, “A Framework for Call Graph Construction Algorithms”, TOPLAS 23(6), 2001,§10.1.6:RTA的全局活类集合