标准Sun javac可以进行增量编译吗?

问题描述 投票:0回答:4

最近我开始使用Eclipse的java编译器,因为它比标准javac要快得多。有人告诉我它更快,因为它执行增量编译。但我对此仍然有点不确定,因为我找不到任何关于 eclispse 和 sun 编译器“增量功能”的权威文档。 Sun 的编译器总是编译每个源文件,而 Eclipse 的编译器仅编译已更改的文件以及受此类更改影响的文件,这是真的吗?

编辑:我没有使用 Eclipse 自动构建功能,而是进行设置

-Dbuild.compiler=org.eclipse.jdt.core.JDTCompilerAdapter

用于我的蚂蚁构建。

java eclipse javac sun incremental-compiler
4个回答
16
投票

Sun 的编译器总是编译每个源文件,而 Eclipse 的编译器只编译已更改的文件以及受此类更改影响的文件,这是真的吗?

我相信你在这两点上都是正确的。

您当然可以强制 Eclipse 重新编译所有内容。

但是等式的另一部分是像 Ant 和 Maven 这样的 Java 构建工具只能编译已更改的类及其依赖类树。

编辑

在 Ant 中,增量编译可以通过两种方式完成:

  • 默认情况下,

    <javac>
    任务会比较
    .java
    和相应的
    .class
    文件的时间戳,并仅告诉Java编译器重新编译比相应目标(.class)更新的源(.java)文件文件,或者根本没有目标文件。

  • <depend>
    任务还考虑了类之间的依赖关系,它通过读取和分析嵌入在
    .class
    文件中的依赖关系信息来确定。 确定哪些
    .class
    文件已过期后,
    <depend>
    任务将删除它们,以便后续
    <javac>
    任务将重新编译它们。 然而,这并非完全万无一失。 例如,对源代码的大量更改可能会导致
    <depend>
    任务可能正在分析过时的依赖项。 此外,某些类型的依赖性(例如静态常量)在
    .class
    文件格式中并不明显。

    要了解为什么 Ant

    <depend>
    并非万无一失,请阅读 文档的“限制”部分。


5
投票

Javac 仅编译在命令行上命名的源文件或依赖项且已过时的源文件。 Eclipse 可能有更细粒度的方式来决定这意味着什么。


2
投票

Eclipse 确实做到了这一点。如果您打开了该选项(默认情况下),它也会在节省时间的情况下执行此操作。看起来sun也没有这样做(这很容易测试,只需做一个小项目,其中A是使用类B的主类,但B不使用类A。然后更改A并编译项目再次查看

b.class
的时间戳是否已更改。

这是许多编译器的工作方式(例如 gcc)。您可以使用 ant 和 make 等工具仅编译项目已更改的部分。另请注意,这些工具并不完美,有时 Eclipse 会丢失对更改的跟踪,您需要进行完全重建。


2
投票

重申我在这里听到的内容,并为像我这样的懒人表述:

您可以使用 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>
© www.soinside.com 2019 - 2024. All rights reserved.