找出一种方法是否可以调用另一种方法 [英] Find out if one method could call another

查看:123
本文介绍了找出一种方法是否可以调用另一种方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to figure out how to take a Java pojo, and analyze its method for all other methods and function it could call. For example, here is a hardcoded example of the output. How can I make this general? I need to analyze Java objects programmatically to determine what methods they could call if executed. Example:

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);
    }
}


推荐答案

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

What you need is construct a call graph, and then ask if two nodes (a caller and callee) are connected in the call graph. This isn't an easy task.

你需要做什么:


  • 解析构成应用程序的源代码。 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中可以指向的任何东西;当然Z可能是从Z继承的类。如果你看到Y.g = a [...],那么你知道Y中的g可以指向任何可能已经分配给数组a的对象。如果您看到Y.g = bar(...),那么您知道Y中的g可以指向条可能返回的任何内容;不幸的是,你现在需要一个调用图来狭隘地回答这个问题。您可以通过各种方式对此进行近似,以获得保守的答案。现在您已经知道值是如何相互关联的,您必须对此集合进行传递闭包,以了解每个Y中的每个g可以指向的内容。如果考虑到各个方法的控制和数据流,您可以得到更精确的答案,但这是构建的更多机制。 (以下是有关指向分析的详细信息。)Java编译器在编译时计算这些信息,但不是整个源文件系统;记住它一次处理一个源文件。我认为JDT根本不会尝试这样做。我们的DMS没有(还)做到这一点,但我们已经为C代码为2600万行的系统做了这个。这可能是一个更难的问题,因为人们使用包括演员表在内的指针来做各种各样的侮辱事。

  • 最后你可以构建一个调用图。对于每个方法,构造一个调用图节点。对于方法中的每个调用站点,确定其callees集并将调用节点链接到被调用节点。上一步收集了提供这些链接所需的信息。

  • Parse the source code making up your application. Java parsers are relatively easy to find. Java 1.8 parsers, not so easy but there's one hiding in the Java compiler you can use, and another in the Eclipse JDT; my company also provides one with our DMS Toolkit.
  • Build abstract syntax trees for same; you need the code structures. The Java compiler, JDT, and DMS can all do this.
  • Perform name and type resolution. You need to know what the definition of every symbol means. The Java compiler definitely does this for one compilation unit at a time. JDT may do it for many files; I don't have a lot of experience with this. DMS can do this for very large sets of Java source files at once.
  • Now you need to do a (object) points-to analysis: you want to know, for any (object-valued) field, what specific instance objects it might point-to; that will eventually tell you what methods it might be used to trigger. You will get the information for this task by inspecting the ASTs and the symbol table definitions that tell what each symbol means. If you see X.f=new foo; you know that f in X can point to foo, as a basic fact. Generics and type erasure make this messy. If you see Y.g=Z.h, you know that g in Y can point to anything that h in Z can point to; of course Z might be class that inherits from Z. If you see Y.g=a[...], then you know that g in Y can point to any object that might have been assigned to array a. If you see Y.g=bar(...) then you know that g in Y can point to anything the bar might return; unfortunately, you now need a call graph to answer the question narrowly. You can approximate this in various ways to get a conservative answer. Now that you know how values are related to one another, you have to take a transitive closure over this set, to get some idea of what each g in each Y can point-to. You can get a more precise answer if you take into account the control and the data flow of the individual methods, but that's more machinery to construct. (Here are more details on points-to analysis.) The Java compiler computes some of this information when it is compiling, but not for an entire system of source files; remember it is processing source files one at a time. I don't think JDT attempts to do this at all. Our DMS doesn't (yet) do this, but we have done this for systems of C code of 26 million lines; this arguably a harder problem because people do all kinds of abusive things with pointers including casts that lie.
  • Finally you can construct a call graph. For each method, construct a call graph node. For each call site in a method, determine its set of callees and link the calling node to the called node. The previous step has collected the information needed to provide these links.

[您可能可以避免解析/名称类型解析以上部分使用 Wala ,它基本上是通过完成上述大部分工作而构建的。

[You might be able to avoid the parsing/name-type resolution part of the above using Wala, which is constructed essentially by doing most of the above].

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

With the call graph, if you want to know if A can call B, find the node for A in the call graph, and see if there is a path to B.

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

Another note here suggests this is a 6 month task for a compiler class. I think it is 6 months for an experienced compiler person, or more (and we haven't addressed nasty problems such as class loaders and reflective calls).

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

I think you are better off finding a solution for this, that somebody else has already built. Likely somebody has; not so likely it is easily found or she wants to part with it. You might find implementations done in Univerisities; there are all kinds of papers written by academics (and supported by a prototype) to compute object-graphs. The down side is all those systems are prototypes, and being build by small, unpaid teams of graduates, they usually don't handle all the edge cases let alone the latest version of Java (lambdas, anyone?)

这篇关于找出一种方法是否可以调用另一种方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆