我们需要留意一下的是第三个调用点, A.foo() 也在其结果之内,因为对于 B 类本身的方法派发得到的结果是 A.foo()
而且,CHA的Resolve算法只关心声明类型,因此 new B() 其实并没有在算法中发挥作用,从而我们 Resolve(b.foo()) 产生了两个虚伪(Spurious)的目的调用 C.foo() 和 D.foo() CG构建示例:
class A {
static void main() {
A.foo();
}
static void foo() {
A a = new A();
a.bar();
}
void bar() {
C c = new C();
c.bar();
}
}
class B extends A {
void bar() { }
}
class C extends A {
void bar() {
if (...) {
A.foo();
}
}
void m() { }
}
复制代码
CHA最终构建的CG如下:
在上述例子当中需要留意的是,固然 A a = new A() ,但是解析 a.bar() 的目的方法时候,依旧会对 A 以及 A 的所有子类作 Dispatch ,故而会有3条从 a.bar() 出发的边。
最后我们会发现存在一个不可达的方法(Unreachable Method) C.m() ,那么这个方法中的代码就是死代码(Dead Code,即在任何环境下控制流都不能到达的代码)。 CHA的应用:IDE中的目的方法提示
2.ICFG 过程间控制流图