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

时间:2019-05-08 20:23:07

标签: java javac

关于使用12.sourcepath参数决定要编译的内容,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.class(具有更新的时间戳),但是未重新编译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!");
    }
}

源文件是相同的,除了所有内容都移动到一个包中。我们希望在当前位于“ 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无条件重新编译所有依赖的源文件?

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

编辑:因为我已经接受了另一个答案作为最佳解释,所以我删除了关于这是一个错误的建议。

顺便说一句,似乎没有明智的方法将此错误报告给OpenJDK。我在OpenJDK网站上搜索和搜索,似乎bugs.openjdk.java.net仅适用于受信任的开发人员。我想我可以把它放到OpenJDK邮件列表中,但这似乎是一个hack。因此,遗憾的是,我什至不知道在哪里报告此错误。

答案 2 :(得分:0)

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

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

一切正常(在我这里):无需重新编译B.java。

这也可能是由于-classpath引起的,但是我宁愿想到包路径的一些深奥的问题。