2012-07-04 154 views
1

嗯,首先,这可能是愚蠢和疯狂的。Java源代码依赖关系图

我正在尝试构建(或使用,如果已经存在的话)一个框架,它接收大量Java源文件并输出这些文件交互的方式;例如,file1.java可能会导入 file2.java; file2.java可以从file3.java调用静态方法。如果这可以在不编译或运行该组文件的情况下完成,那理想情况下会很好。我意识到Reflection API可以让我探索一个类的各个部分,但是我正在寻找什么?

此外,如何将其扩展到其他语言,例如Python或Lisp(在此添加任何其他语言)?

我真的不确定如何构建问题标题,所以如果之前有人问过这样的问题,我会很高兴能否将我与该问题联系起来。

+0

从技术上说,你不要导入文件 - 导入仅仅是由编译器使用时,使用非完全限定类名来解决完全限定类名。 –

+0

通过反射,您可以查看类中的字段,方法的参数和返回类型 - 但反射不会告诉您有关在*方法中使用的类的任何内容。 –

+0

查看OpenJDK的来源?我认为你正在做一些编译器已经在做的事情。 – nhahtdh

回答

1

你有两个问题,我会试着解决第一个问题。我相信你正在对java文件进行一些源分析,看看它们是如何相互交互的(至少这就是我所理解的)。所以基本上,要做到这一点,你必须像Eclipse IDE一样行事。扫描每个.java文件中的源代码并构建java保留字和构造的数据结构。一旦分析了每个.java文件,您就可以继续发现它们之间的链接。

ex。

  1. 存储类,它的名字和它的范围
  2. 存储所有声明的变量,它们的值的HashMap和其范围
  3. 查看源文件的方法和存储他们的名字的包名, in + out参数和范围

您也可以做更多的事情,并检测这些结构,您必须编写自己的(或网上找到的东西)解析器并使用正则表达式来检测这些结构。您将它们存储在您的程序中,然后一旦分析完所有源文件,就可以开始查看交互。

ex。

源文件1位于软件包x.y中,有3个公共方法和2个软件包范围方法。 源文件2位于包z中,有1个公共方法和3个私有方法。

所以你可以得出结论,文件1可以通过调用该公共方法与文件2进行交互。你可以对所有文件进行相同的分析。

+0

这听起来很有趣,但我不确定它有多可行。我可能会等待更多的答案。 – Gooner

+0

这是100%可行的,我们在大学学习这个东西。通常当然是以“编译器构造”的名义。你基本上是在编码解析器和分析源代码并映射它的每一个部分。然后,您只需根据规则找到映射之间的连接。并且这些规则在JVM规范中定义。 –

+0

如果有时间我可以给你写一个示例程序,它可以完成我所提到的任务。如果你怀疑我建议的可行性,就像是一个真正基础的概念证明。 –

2

我目前工作的一个项目,主要功能是非常相似,你所提到的,我用的是JavaParser类:http://code.google.com/p/javaparser/

JavaParser类是非常强大的,它可以帮助我们在源代码分析了很多,但即使我使用javaparser,也很难获得完整的依赖关系和类交互。

例如: 如果您想获得类的所有依赖关系,最直接的方法是获取源代码的“导入”区域 - 使用javaparser可以非常容易。但是只有“导入”是不够的,如果ClassA - 您当前正在分析的类叫做ClassB - 它与ClassA位于同一个包中,那么ClassB将不会出现在导入区域中。

所以在这种情况下,我们无法得到ClassB的依赖。

对于类的交互,如果你不能100%获得一个类的正确依赖关系,那么你不能100%知道类之间的正确的交互。

但无论如何,到目前为止,javaparser是我能找到的功能最强大,最实用的java源代码分析工具。

+0

好的,我建议这次使用:ANTLR(http://www.antlr.org/)。 ANTLR是编程语言解析和处理的最佳解决方案。 –

0

我知道你说你宁愿不做编译,但通过类文件浏览会容易得多。在字节码和常量池之间,你可以得到你需要的一切,而不必求助于重写javac。使用Apache BCEL,你大部分都在那里。显然没有工具能够找到通过反射访问的依赖关系;为此,您需要使用自定义类加载器或其他方法进行运行时分析。

https://en.wikipedia.org/wiki/Java_class_file http://commons.apache.org/proper/commons-bcel/

+0

它可能会更容易,但它也是错误的。 javac在源文件中内联常量,这意味着您可以使A.java取决于B.java,但A.class不参考B.class。 –