4

The java 12.0.1 compiler (my tests here are all run in MS Windows) has some really odd behavior when using the -sourcepath argument, with regards to what it decides to compile. The easiest way to explain this is to provide two examples and cite the differences in behavior.

Example 1:

Source file "A.java"

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

Source file "B.java"

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

To compile example 1, we just use the following:

javac -sourcepath . A.java

This will compile both A.java and B.java and create A.class and B.class. We expect it to also compile B.java because A depends on it. Now wait a second or so and without modifying either ".java" source file, simply re-run the compilation command above. You will find that it re-compiles A.java and a new A.class is created (with updated timestamp), but B.class is not re-compiled. Ok, this is pretty much what one might expect. Now let's compare this to the next example below.

Example 2:

Source file "example2/A.java"

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

Source file "example2/B.java"

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

The source files are the same, except everything is moved into a package. We want to compile the two source files while currently in the "example2" folder. So we use the following command:

javac -sourcepath .. A.java

This will again compile both A.java and B.java and create A.class and B.class. No problems here, same as before. Note that -sourcepath is now ".." because that is the "root" source folder now that everything is in a package. Now wait a second or so and without modifying either source file, simply re-run the compilation command above. You will find that it re-compiles BOTH A.java and B.java and a new A.class and B.class file are created (with updated timestamps).

Note the difference in compilation behavior when the javac command is run the second time. When -sourcefile was "." and the files were not in a package, the second "javac" command only compiles the source file specified on the command line. But when -sourcefile is ".." and the classes are in a package, the second "javac" command ALWAYS compiles all the dependent source files, regardless if the unspecified source files need to be recompiled or not.

The question is why? What arguments can I pass to the javac command-line to stop example 2 from unconditionally recompiling all the dependent source files, if their class files have a newer timestamp than the source files?

4
  • 1
    Here's a third experiment, try compiling just B in example 2 :) Commented May 8, 2019 at 20:33
  • @yhyrcanus Then it only recompiles B, as expected. Attempts to recompile A only, result in B also being recompiled because there is a dependency that javac detects. Problem is, B doesn't need to be recompiled because it's already up to date. This isn't a big deal with 2 source files, but when there's dozens of source files, it matters. Commented May 8, 2019 at 20:37
  • You're doing it wrong. You should be in .., that is to say in the directory that contains the head of the package structure, and the command should be javac example2/A.java etc. Commented May 9, 2019 at 0:16
  • 1
    @user207421 Then what's the purpose of the -sourcepath option? If you "must" be in the root source folder when compiling, why even have a command-line option that allows you to be in a different folder? Clearly that's the whole point of -sourcepath, i.e. to allow you to compile from whatever folder you want. Commented May 9, 2019 at 12:36

3 Answers 3

3

This issue occurs because javac compares timestamps between the .java file and the .class file. It uses -sourcepath to find the source files, and -classpath to find the class files. Therefore, your issue can be fixed by specifying the classpath:

javac -sourcepath .. -classpath .. A.java
Sign up to request clarification or add additional context in comments.

1 Comment

This seems to be the best explanation, and the fix works.
0

This seems related to ... If you go to the source root, the default package:

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

everything works (at my place): no recompile of B.java.

It might be due to the -classpath too, but I would rather think of some esoteric problem with package paths.

1 Comment

Yes this is a workaround, but it also defeats the whole purpose of the -sourcepath command-line option, which enables you to be in whatever current directory you want, when compiling source files.
0

EDIT: I've removed my suggestion that this is a bug, since I've accepted another answer as the best explanation.

As an aside, there seems to be no sensible way to report this as a bug to the OpenJDK. I googled and searched around the OpenJDK website and it seems that the bugs.openjdk.java.net is only for trusted developers. I guess I could throw it up on the OpenJDK mailing list, but that seems like a hack. So I am not even sure where to report this bug, sadly.

3 Comments

I don't know if it's a bug but if you want to report one: mail.openjdk.java.net/pipermail/discuss/2015-December/…
It's the same behaviour in javac version 1.8.0_212.
@assylias Well that thread is an interesting discussion between a bunch of people arguing about where to report OpenJDK bugs, but it doesn't actually suggest a usable answer, other than to suggest reporting it to Oracle at bugreport.java.com which is probably creating a non-public report that only Oracle will look at. Doesn't OpenJDK want its community to be able to report bugs somewhere other than Oracle's private bug database?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.