Java 如何获得编译器编译一个类所需的所有源代码的列表

Java 如何获得编译器编译一个类所需的所有源代码的列表,java,java-compiler-api,Java,Java Compiler Api,为了在运行时创建和加载一个类,我首先从数据库中读取它的内容,创建一个新的SimpleJavaFileObject,最后在运行时通过将它传递给CompilationTask来编译它。 关键是,这个新文件可能引用其他文件(直接导入或通过de.package.*“间接”导入),这些文件也存储在db中,不能作为类或源代码文件使用 public class Test1 { public de.otherpackage.Test2 reply() { return null;

为了在运行时创建和加载一个类,我首先从数据库中读取它的内容,创建一个新的SimpleJavaFileObject,最后在运行时通过将它传递给CompilationTask来编译它。 关键是,这个新文件可能引用其他文件(直接导入或通过de.package.*“间接”导入),这些文件也存储在db中,不能作为类或源代码文件使用

public class Test1 {
     public de.otherpackage.Test2 reply() {
          return null;
     }
}
与Test1一样,我必须提前一步创建和编译Test2,因为没有JavaFileObject或类可供编译器使用

那么:如何获得编译器编译一个类所需的所有源代码的列表

知道Test1需要Test2就足够了。我首先通过向CompliationTask传递一个处理器来尝试它。我检查了树中的所有属性,但没有发现任何有用或完整的属性。如果在包上使用*导入类,则无法获得完整的限定名。。。至少对我来说不是这样:-/

有什么想法吗?也许有更好的方法来解析javasources


感谢您的帮助:-)

如果您在编译类之前询问是否有这样做的方法,那么答案是“没有”。源代码和源代码本身决定了直接依赖关系。您需要编译源代码以提取它们


如果您询问是否有方法在编译时或编译后提取依赖项,那么有几种替代方法:

  • javac
    命令有一个
    -verbose
    选项,使其列出加载的每个类和编译的每个文件

  • 如果使用标准编译器API,它将提供用于加载依赖类和定位源文件的挂钩。你可以用这些来追踪发生了什么

  • 您可以从字节码文件本身获取大部分信息。不过有几个警告:

    • 如果代码是用
      -g:none
      编译的,.class”文件中不会有源文件名

    • 您可以通过不记录编译时间来确定依赖项。。。除非您可以从文件时间戳推断它们

    • 对另一个类中声明的编译时常量的依赖关系在编译时完全解析(并内联)。。。并且在生成的“.class”文件中不会有任何跟踪


但是请注意,编译类通常不需要这样做。如果编译器发现它需要加载或编译依赖类,它会自动执行。至少,默认情况下,
javac
就是这样运行的。

使用
import-package.*
是不好的做法。一些指南说您可以在最终提交之前将其用于开发和更改,但我认为使用现代IDE应该完全避免。无论如何,如果您使用的是一个代码库位于DB中的系统,该系统应该提供这样一个系统(在正常Java机制之外)。您所说的是什么意思“该系统应该提供这样一个系统(在普通Java机制之外)”?有没有办法在Java代码之外编译这些文件?a)因为Java不做这些事情(它希望您提供所需的依赖项),这就是为什么我们在项目和工具中使用IDE,如
Ant
Maven
,以及b),因为对系统的描述很奇怪而且太简单(如果您正在编译文件的版本2.4.6,您如何管理您需要版本2.4.1的源代码
b
);如果它是一种商业产品,它应该提供一种方法,如果它是一种自制的装置(感觉就像这样),忘记它,为你的OSB找到一种适合你的产品(免费或付费)。我会忘记DB的想法,使用更标准的机制(v.g.SVN).Hi Stephen.是的,我在编译之前或编译时需要文件信息。由于我使用Java编译器API,我对在加载类/依赖项时挂接的方式感兴趣。正如我所说,我使用处理器进行了尝试,但当代码包含多个*导入时,我得到的所有信息都不充分。因此我还没有找到这样做的方法.