找出一种方法是否可以调用另一种方法

Dav*_*ams 6 java static-analysis

我试图找出如何获取Java pojo,并分析其方法可以调用所有其他方法和函数.例如,这是输出的硬编码示例.我该怎么做这个一般?我需要以编程方式分析Java对象,以确定执行时可以调用的方法.例:

package com.example.analyze;

public class Main
{

    private static class Foo {

        public void foo(int value, Bar bar) {
            if(value > 5)
                bar.gaz();
        }
    }

    private static class Bar {

        public void gaz() {
            System.out.println("gaz");
        }
    }

    private static class Analyzer {

        public void analyze(Object object){
            System.out.println("Object method foo could call Bar method gaz");
        }

    }

    public static void main(String[] args)
    {
        Foo foo = new Foo();
        Analyzer analyzer = new Analyzer();
        analyzer.analyze(foo);
    }
}
Run Code Online (Sandbox Code Playgroud)

Ira*_*ter 8

你需要的是构造一个调用图,然后询问调用图中是否连接了两个节点(一个调用者和被调用者).这不是一件容易的事.

你需要做什么:

  • 解析构成应用程序的源代码.Java解析器相对容易找到.Java 1.8解析器,不是那么容易,但是你可以使用Java编译器中的一个,而Eclipse JDT中的另一个; 我的公司还提供了一个我们的DMS工具包.
  • 为它构建抽象语法树; 你需要代码结构.Java编译器,JDT和DMS都可以这样做.
  • 执行名称和类型解析.你需要知道每个符号的定义是什么意思.Java编译器一次只为一个编译单元执行此操作.JDT可以为许多文件执行此操作; 我对此没有太多经验.DMS可以同时为非常大的Java源文件集执行此操作.
  • 现在你需要做一个(对象)点分析:你想知道,对于任何(对象值)字段,它可能指向哪些特定的实例对象; 这将最终告诉你它可能用于触发的方法.您将通过检查AST和符号表定义来获取此任务的信息,这些定义告诉每个符号的含义.如果你看到Xf = new foo; 你知道X中的f可以指向foo,这是一个基本事实.泛型和类型擦除使这个混乱.如果你看到Yg = Zh,你知道Y中的g可以指向Z中可以指向的任何东西; 当然Z可能是从Z继承的类.如果你看到Yg = a [...],那么你知道Y中的g可以指向任何可能已经分配给数组a的对象.如果您看到Yg = bar(...),那么您知道Y中的g可以指向条可能返回的任何内容; 不幸的是,你现在需要一个调用图来狭隘地回答这个问题.您可以通过各种方式对此进行近似,以获得保守的答案.现在你已经知道了值是如何相互关联的,你必须对这个集合进行传递闭包,以便了解每个Y中每个g可以指向的内容.如果考虑到各个方法的控制和数据流,您可以得到更精确的答案,但这是构建的更多机制.(以下是有关点到分析的更多详细信息.)Java编译器在编译时会计算其中的一些信息,但不会对整个源文件系统进行计算.记住它一次处理一个源文件.我认为JDT根本不会尝试这样做.我们的DMS没有(还)做到这一点,但我们已经为C代码为2600万行的系统做了这个.这可能是一个更难的问题,因为人们用指针包括演员谎言来做各种各样的辱骂事.
  • 最后,您可以构建一个调用图.对于每个方法,构造一个调用图节点.对于方法中的每个调用站点,确定其callees集并将调用节点链接到被调用节点.上一步收集了提供这些链接所需的信息.

[您可能能够避免使用Wala的上述解析/名称类型解析部分,Wala基本上是通过执行上述大部分工作构建的].

使用调用图,如果您想知道A是否可以调用B,请在调用图中找到A的节点,并查看是否有到B的路径.

这里的另一个注意事项表明这是编译器类的6个月任务.我认为对于经验丰富的编译人员来说,这是6个月,或者更多(并且我们没有解决诸如类加载器和反射调用之类的令人讨厌的问题).

我认为你最好找到一个解决方案,其他人已经建立了.有人可能; 不太可能很容易找到它或她想要分开它.您可能会发现在Univerisities中完成的实现; 学术界编写的各种论文(并由原型支持)来计算对象图.缺点是所有这些系统都是原型,并由小型,无偿的毕业生团队构建,他们通常不处理所有边缘情况,更不用说最新版本的Java(lambdas,任何人?)