如果项目正在使用 Java8,我如何通过静态分析检测?

How can I detect by static analysis, if a project is using Java8?

我目前正在使用 javaparser (https://github.com/javaparser/javaparser) and javasymbolsolver(https://github.com/javaparser/javasymbolsolver) 来解析代码。如果我检测到 Collections#Streams 的使用,确定特定项目已迁移到 Java8,这是否是一种整体方法?(假设 Collection#Streams 是使用最广泛的 java8 功能)。

您可以查找 Java8 个特征。

你最好的选择是尝试用 Java7 编译器和 Java8 编译器编译代码 [是的,这被认为是静态分析!],看看哪个给你代码库上的编译错误最少。 (您可以很容易地将其推广到任何 Java vN 编译器)。

如果一个编译器完全成功,而另一个编译器不成功,那么您的答案似乎很清楚。

如果两个编译器都产生错误,您将不得不求助于其他指标(例如,它是否使用 Java8 功能)。

如果代码与两者一起编译,你真的不知道;可能 Java8 的一些黑暗语义角落被批判性地使用了。此时此刻,唯一的办法就是告诉 是 运行 功能回归测试,并选择通过最多测试的一项。

我可以在这里看到多种方法,包括基于源代码和基于二进制文件的方法,寻找 Java 8 APIs 和寻找 Java 8 语言特性。

寻找 Java 8 APIs

寻找源代码中常见的Java8API(简单)

您可以解析代码并查找首次出现在 Java 8 中的 API - 正如您在回答中所建议的那样。 Java 8 API 最广为人知的功能是流和 Optional class,以及 java.util.function 包。我希望几乎所有迁移到 Java 8 的项目都能使用这些功能。

在源代码中查找所有 Java 8 APIs(高级)

如果特定项目使用 Java 8 API 或不使用,要获得 100% 的答案,您需要查找的不是一些,而是所有添加的 API在 Java 8. 可能有很多方法可以找到该列表,但是有一个名为 Sigtest 的工具专门用于比较产品不同版本的 API(在这种情况下产品是 Java 本身)。

在二进制文件中做同样的事情

可能更便宜的方法是使用二进制文件而不是源文件。所有外部链接都放在 .class 文件的开头,在称为常量池的部分中。有一些工具可以帮助您提取这些数据,例如ClassDep(它作为 Apache River 的一部分分发,但您可以单独使用它)。

检查语言版本

检查 class 二进制文件版本

对于每种语言版本,class 文件中记录了不同的版本。 Java 7 为 51.0,Java 8 - 52.0,Java 9 - 53.0。 javap JDK 附带的工具在使用 -v 选项启动时打印此版本。

寻找 Java 8 种语言功能

由于您使用的是源代码,我假设您的解析器支持 Java 8。如果是这样,它将能够识别 Java 8 种语言结构,例如 lambda 和方法引用. Java 8 种语言功能的完整列表(好吧,我假设它是完整的)是 here.

关于结果的准确性

每种方法的准确性取决于问题是什么。如果它是 "Does a project use Java 8 at all?" 那么没有任何一种方法会给出 100% 的结果。正如 Holger 在他的评论中指出的那样,可能存在部分迁移的项目,这些项目仅为 Java 8 编译并且不使用其任何 API,或者仅使用 Java 8 APIs 但编译为 Java 7.

问题 "Does a project use compilation with language level 8?" 最好通过 class 文件版本分析来回答 - 任何使用 lambda 的 class 都将具有版本 52.0,但反之则不然。

问题"Does a project use Java 8 APIs?",显然,需要参考文献分析。我只能推测对选定的 APIs 的分析是否足够 - 像您正在做的那样的研究可以给出答案。