我试图弄清楚如何获取 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);
}
}
您需要的是构造一个调用图,然后询问调用图中两个节点(调用者和被调用者)是否连接。这不是一件容易的事。
你需要做什么:
- 解析构成您的应用程序的源代码。 Java 解析器相对容易找到。 Java 1.8 解析器,不是那么容易,但是有一个隐藏在您可以使用的 Java 编译器中,另一个隐藏在 Eclipse JDT 中;我公司还随 DMS 工具包提供了一个。
- 为其构建抽象语法树;你需要代码结构。 Java编译器、JDT和DMS都可以做到这一点。
- 执行名称和类型解析。您需要知道每个符号的定义意味着什么。 Java 编译器肯定会一次针对一个编译单元执行此操作。 JDT 可以对许多文件执行此操作;我对此没有太多经验。 DMS 可以同时对非常大的 Java 源文件集执行此操作。
- 现在您需要进行(对象)指向分析:您想知道,对于任何(对象值)字段,它可能指向哪些特定实例对象;这最终会告诉你它可能被用来触发什么方法。您将通过检查 AST 和说明每个符号含义的符号表定义来获取此任务的信息。如果您看到 X.f=new foo;你知道 X 中的 f 可以指向 foo,这是一个基本事实。泛型和类型擦除让这一切变得混乱。如果你看到Y.g=Z.h,你就知道Y中的g可以指向Z中的h可以指向的任何东西;当然,Z 可能是继承自 Z 的类。如果您看到 Y.g=a[...],那么您就知道 Y 中的 g 可以指向可能已分配给数组 a 的任何对象。如果您看到 Y.g=bar(...) 那么您就知道 Y 中的 g 可以指向 bar 可能返回的任何内容;不幸的是,您现在需要一个调用图来狭隘地回答这个问题。您可以通过多种方式近似这一点以获得保守的答案。现在您知道了值之间如何相关,您必须对该集合采用传递闭包,以了解每个 Y 中的每个 g 可以指向什么。如果考虑各个方法的控制和数据流,您可以获得更精确的答案,但这需要更多的机械构造。 (这里有更多详细信息点分析 http://www.seas.harvard.edu/courses/cs252/2011sp/slides/Lec06-PointerAnalysis.pdf.) Java 编译器在编译时会计算其中一些信息,但不会计算整个源文件系统;请记住,它一次处理一个源文件。我认为 JDT 根本不会尝试这样做。我们的 DMS 还没有做到这一点,但我们已经对 2600 万行 C 代码的系统做到了这一点;这可以说是一个更难的问题,因为人们用指针做各种滥用的事情,包括撒谎的强制转换。
- 最后你可以构建一个调用图。对于每个方法,构造一个调用图节点。对于方法中的每个调用站点,确定其被调用者集并将调用节点链接到被调用节点。上一步已收集了提供这些链接所需的信息。
[您也许可以使用以下方法避免上面的解析/名称类型解析部分Wala http://wala.sourceforge.net/wiki/index.php/Main_Page,它基本上是通过执行上述大部分操作来构建的]。
通过调用图,如果你想知道A是否可以调用B,就在调用图中找到A的节点,看看是否有到B的路径。
这里的另一个注释表明,对于编译器类来说,这是一项为期 6 个月的任务。我认为对于一个有经验的编译器人员来说这是 6 个月,或者更多(而且我们还没有解决类加载器和反射调用等讨厌的问题)。
我认为你最好找到一个其他人已经构建的解决方案。可能有人有;它不太可能轻易找到,或者她想放弃它。您可能会发现在大学中完成了实施;学者们撰写了各种各样的论文(并有原型支持)来计算对象图。缺点是所有这些系统are原型,并且是由小型、无薪的毕业生团队构建的,他们通常不能处理所有的边缘情况,更不用说最新版本的 Java(lambdas,有人吗?)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)