最近我开始使用Eclipse的java编译器,因为它比标准javac要快得多。有人告诉我它更快,因为它执行增量编译。但我对此仍然有点不确定,因为我找不到任何关于 eclispse 和 sun 编译器“增量功能”的权威文档。 Sun 的编译器总是编译每个源文件,而 Eclipse 的编译器仅编译已更改的文件以及受此类更改影响的文件,这是真的吗?
编辑:我没有使用 Eclipse 自动构建功能,而是进行设置
-Dbuild.compiler=org.eclipse.jdt.core.JDTCompilerAdapter
用于我的蚂蚁构建。
Sun 的编译器总是编译每个源文件,而 Eclipse 的编译器只编译已更改的文件以及受此类更改影响的文件,这是真的吗?
我相信你在这两点上都是正确的。
您当然可以强制 Eclipse 重新编译所有内容。
但是等式的另一部分是像 Ant 和 Maven 这样的 Java 构建工具只能编译已更改的类及其依赖类树。
编辑
在 Ant 中,增量编译可以通过两种方式完成:
<javac>
任务会比较.java
和相应的.class
文件的时间戳,并仅告诉Java编译器重新编译比相应目标(.class)更新的源(.java)文件文件,或者根本没有目标文件。<depend>
任务还考虑了类之间的依赖关系,它通过读取和分析嵌入在.class
文件中的依赖关系信息来确定。 确定哪些 .class
文件已过期后,<depend>
任务将删除它们,以便后续 <javac>
任务将重新编译它们。 然而,这并非完全万无一失。 例如,对源代码的大量更改可能会导致 <depend>
任务可能正在分析过时的依赖项。 此外,某些类型的依赖性(例如静态常量)在 .class
文件格式中并不明显。
要了解为什么 Ant
<depend>
并非万无一失,请阅读 文档的“限制”部分。Javac 仅编译在命令行上命名的源文件或依赖项且已过时的源文件。 Eclipse 可能有更细粒度的方式来决定这意味着什么。
Eclipse 确实做到了这一点。如果您打开了该选项(默认情况下),它也会在节省时间的情况下执行此操作。看起来sun也没有这样做(这很容易测试,只需做一个小项目,其中A是使用类B的主类,但B不使用类A。然后更改A并编译项目再次查看
b.class
的时间戳是否已更改。
这是许多编译器的工作方式(例如 gcc)。您可以使用 ant 和 make 等工具仅编译项目已更改的部分。另请注意,这些工具并不完美,有时 Eclipse 会丢失对更改的跟踪,您需要进行完全重建。
重申我在这里听到的内容,并为像我这样的懒人表述:
您可以使用 ant 中的 javac 任务实现增量构建,但您应该使用 dependent 任务来清除修改后的 .java 的 .class 文件,并且不得在 javac 任务中保留未指定的包含语句。 (在 javac 任务中仅指定 src 路径并保留未指定的内容会导致 javac 重新编译它找到的所有源。)
这是我的依赖项和 javac 任务。 使用标准 Oracle java 编译器,仅编译我修改的 .java 文件。 希望这有帮助!
<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>