如何强制Java编译器仅编译我指定的源文件



Java 12.0.1编译器(我的测试都在MS Windows中运行(在使用-sourcepath参数时具有一些非常奇怪的行为,就其决定编译的内容而言。解释这一点的最简单方法是提供两个例子并引用行为差异。

示例1:

源文件" a.java"

public class A {
    public static void main(String[] args) {
        System.out.println("Hello World");
        B.myMethod();
    }
}

源文件" b.java"

public class B {
    public static void myMethod() {
        System.out.println("Goodbye!");
    }
}

要编译示例1,我们只使用以下内容:

javac -sourcepath . A.java

这将同时编译A.Java和B.Java,并创建A.Class和B.Class。我们希望它也可以编译B.Java,因为A取决于它。现在等待一秒钟左右,而无需修改" .java"源文件,只需重新运行上面的汇编命令即可。您会发现它重新编译了A.Java,并创建了一个新的A.类(带有更新的时间戳(,但是B.Class并未重新编译。好的,这几乎是人们所期望的。现在让我们将其与下面的下一个示例进行比较。

示例2:

源文件" example2/a.java"

package example2;
public class A {
    public static void main(String[] args) {
        System.out.println("Hello World");
        B.myMethod();
    }
}

源文件" example2/b.java"

package example2;
public class B {
    public static void myMethod() {
        System.out.println("Goodbye!");
    }
}

源文件是相同的,除了所有内容都移至软件包。我们想在" exame2"文件夹中当前在" example2"文件夹中编译两个源文件。因此,我们使用以下命令:

javac -sourcepath .. A.java

这将再次编译A.Java和B.Java,并创建A.Class和B.Class。这里没有问题,就像以前一样。请注意,-SourcePath现在是" ..",因为现在所有内容都在软件包中,这是"根"源文件夹。现在等待一秒钟左右,而无需修改任何一个源文件,只需重新运行上面的汇编命令即可。您会发现它重新编译A.Java和b.java以及新的A.Class和B.Class文件(带有更新的时间戳(。

请注意,当Javac命令第二次运行时,汇编行为的差异。当-sourcefile是"。文件不在软件包中,第二个" Javac"命令仅编译命令行上指定的源文件。但是,当-sourcefile为" ..",并且这些类位于软件包中时,第二个" Javac"命令总是会编译所有因源文件,而不管是否需要重新编译未指定的源文件。

问题是为什么?如果他们的类文件比源文件更新的时间戳?

,我可以将哪些参数传递给Javac命令行,以阻止示例2无条件地重新编译所有相关的源文件?

此问题之所以发生,是因为Javac比较了.java文件和.class文件之间的时间戳。它使用-sourcepath查找源文件,并使用-classpath查找类文件。因此,可以通过指定类路径来解决您的问题:

javac -sourcepath .. -classpath .. A.java

这似乎与..有关。如果您转到源根,则默认软件包:

cd ..
javac -sourcepath . ex/A.java

一切都起作用(在我的位置(:b.java没有重新编译。

也可能是由于-classpath造成的,但我宁愿想到包装路径的某些深奥问题。

编辑:我已经删除了我的建议,因为我已经接受了另一个答案作为最佳解释。

顺便说一句,似乎没有明智的方法将其报告为OpenJDK的错误。我在OpenJDK网站上搜索并搜索了搜索,似乎Bugs.openjdk.java.net仅适用于受信任的开发人员。我想我可以将其扔到OpenJDK邮件列表上,但这似乎是一个黑客。因此,我什至不确定在哪里报告此错误。

最新更新