标准Sun javac可以进行增量编译吗?
最近我开始使用Eclipse的java编译器,因为它比标准javac快得多。我被告知它更快,因为它执行增量编译。但我仍然有点不确定,因为我找不到任何关于-eclispse和sun的编译器“增量特性”的权威文档。Sun的编译器总是编译每个源文件,Eclipse的编译器只编译更改过的文件和受此更改影响的文件,这是真的吗 编辑:我没有使用EclipseAutobuild特性,而是设置标准Sun javac可以进行增量编译吗?,java,eclipse,compiler-construction,sun,incremental-compiler,Java,Eclipse,Compiler Construction,Sun,Incremental Compiler,最近我开始使用Eclipse的java编译器,因为它比标准javac快得多。我被告知它更快,因为它执行增量编译。但我仍然有点不确定,因为我找不到任何关于-eclispse和sun的编译器“增量特性”的权威文档。Sun的编译器总是编译每个源文件,Eclipse的编译器只编译更改过的文件和受此更改影响的文件,这是真的吗 编辑:我没有使用EclipseAutobuild特性,而是设置 -Dbuild.compiler=org.eclipse.jdt.core.JDTCompilerAdapter 对
-Dbuild.compiler=org.eclipse.jdt.core.JDTCompilerAdapter
对于我的蚂蚁构建 Eclipse确实做到了这一点。此外,如果您启用了该选项(默认情况下),它也会节省时间。看起来sun也没有这样做(这很容易测试,只需制作一个小项目,其中a是使用B类的主类,但B不使用a类。然后更改a并再次编译项目,查看
B.class
的时间戳是否已更改
这是许多编译器的工作方式(例如gcc)。您可以使用诸如ant和make之类的工具来只编译项目中已更改的部分。还要注意,这些工具并不完美,有时eclipse只是无法跟踪更改,您需要进行完整的重建
Sun的编译器总是编译每个源文件,Eclipse的编译器只编译更改过的文件和受此更改影响的文件,这是真的吗
我相信你在这两方面都是正确的
当然,您可以强制Eclipse重新编译所有内容
但等式的另一部分是,像Ant和Maven这样的Java构建工具只能编译已经更改的类,以及它们的依赖类树
编辑
在Ant中,增量编译可以通过两种方式完成:
- 默认情况下,比较
和相应的.java
文件的时间戳,并且只告诉java编译器重新编译比相应的目标(.class)文件新的源(.java)文件,或者根本没有目标文件的源(.java)文件.class
- 还考虑了类之间的依赖关系,它通过读取和分析嵌入在
文件中的依赖关系信息来确定这些依赖关系。在确定哪些.class
文件过期后,.class
任务将删除这些文件,以便后续的
任务将重新编译它们。但是,这并非完全是傻瓜式的。例如,对源代码的大量更改可能会导致
任务可能正在分析过时的依赖关系。此外,某些类型的依赖关系(例如对静态常量的依赖关系)在
文件格式中并不明显 要理解为什么Ant.class
不是傻瓜式的,请阅读的“限制”部分
<depend srcdir="JavaSource" destdir="${target.classes}" cache="${dependencies.dir}" closure="yes">
<classpath refid="compiler.classpath" />
<include name="**/*.java"/>
</depend>
<javac destdir="${target.classes}" debug="true" debuglevel="${debug.features}" optimize="${optimize.flag}" fork="yes" deprecation="no" source="1.6" target="1.6" encoding="UTF-8" includeantruntime="no">
<classpath refid="compiler.classpath"/>
<src path="JavaSource"/>
<include name="**/*.java" /> <!-- This enables the incremental build -->
</javac>
您能解释一下使用Ant进行部分编译是如何工作的吗?Ant是如何强制Sun的编译器只编译更改过的文件而忽略源代码树中的其他文件的?我想您回答了我最初的问题,但随着您提供的信息越来越多,我越来越困惑。如果我理解正确,我觉得Java C任务与您无关t previous clean是一个非常危险的操作,因为如果不更改依赖类的时间戳,它就不会编译这些依赖类。(有趣的是,我昨天才意识到我可能遇到了这个问题,对我来说,这完全是个谜。)如果依赖类没有更改,为什么需要编译它?因为它所依赖的类型或方法签名已经更改。或者因为它所依赖的编译时常量已经更改。ant可以做到这一点,但maven似乎不能做到这一点。你可以链接一些支持此答案的文档吗?我认为1)依赖项不是由纯javac编译的,2)Eclipse有它自己的、完全不同的编译器,而不仅仅是更细粒度的决定方式。我也不能证明,但这就是为什么我问:)。。。。当然,你可以证明这一点:只需设置我描述的条件,你自己就会看到。这是正确的:javac编译你告诉它要编译的文件,而不是“每个源文件”。它不会自行决定需要编译哪些文件,因此它不是OP所要求的增量。此外(正如EJP所说),当javac编译类A并找到A所依赖的其他.java文件时,它(取决于许多因素)也会编译它们。这与查找可能受A.java更改影响的文件不同,我认为这是人们感到困惑的地方。@gatkin你自相矛盾。为了澄清或重申,javac编译您告诉它的每个文件以及它能够检测到的任何过时的依赖项,它确实“决定”了这些依赖项@EJP我发表了评论,解释了我为什么投票给您。关于javac的功能,我们都说了同样的话。它没有做的是寻找过时的依赖项,就像Eclipse一样,这正是OP所要求的。尽管我认为你的回答是正确的,我也这么说了,但我认为最后一点值得一提