How are multiple Java files compiled together?

Discussion in 'Java' started by Jason Kim, May 27, 2012.

  1. Jason Kim

    Jason Kim Guest

    I am new to Java.

    Here are two files.
    class VolcanoApplication {
    public static void main(String[] arguments) {
    VolcanoRobot dante = new VolcanoRobot();
    dante.status = "exploring";
    dante.speed = 2;
    dante.temperature = 510;

    System.out.println("Increasing speed to 3.");
    dante.speed = 3;
    System.out.println("Changing temperature to 670");
    dante.temperature = 670;
    System.out.println("Checking the temperature.");
    class VolcanoRobot {
    String status;
    int speed;
    float temperature;

    void checkTemperatur() {
    if (temperature > 50) {
    status = "returning home";
    speed = 5;

    void showAttributes() {
    System.out.println("Status: " + status);
    System.out.println("Speed: " + speed);
    System.out.println("Temperature: " + temperature);

    I compiled the program by doing
    $ javac

    But how does Java know that should also be in the compilation?
    Jason Kim, May 27, 2012
    1. Advertisements

  2. If it didn't know, think about what a pain that would be every time you
    had to compile a program with a lot of files. You reference
    VolcanoRobot in VolcanoApplication, the compiler looks for that that
    class in the classpath and compiles it if necessary.

    That feature can be the source of a very tricky problem and that is if
    there is a VolcanoRobot.class file in the classpath the compiler won't
    compile even if it has changed since the
    VolcanoRobot.class file was created.
    Knute Johnson, May 28, 2012
    1. Advertisements

  3. Jason Kim

    Jason Kim Guest

    I didn't know Java compiler could be that smart.
    As for the potential problem you mentioned, I don't think I'll have to worry about it any time soon. I won't be programming anything crazy complicated for some time.
    Thanks Knute.
    Jason Kim, May 28, 2012
  4. Jason Kim

    Roedy Green Guest

    1. say javac *.java

    2. compiler sees you calling some method and it can't find the class
    file for it. So it looks on the sourcepath for the *.java file to

    3. It can compare the dates on the class file and corresponding *.java
    file. If the *.java file is newer it knows to recompile.

    4. Use ANT. See
    Roedy Green Canadian Mind Products
    I would be quite surprised if the NSA (National Security Agency)
    did not have a computer program to scan bits of shredded
    documents and electronically put them back together like a giant
    jigsaw puzzle. This suggests you cannot just shred, you must also burn.
    Roedy Green, May 28, 2012
  5. Jason Kim

    Roedy Green Guest

    This gives me trouble all the time. Javac can recompile code with
    target 1.7 that was intended to be compiled with 1.6 if it gets
    recompiled as a side effect of compilng something with 1.7.

    I wrote a utility to make
    sure everything is the version it is supposed to be. If it is out of
    whack, I manually clean compile it. If it is really screwed up, I do
    a clean rebuild of everything.
    Roedy Green Canadian Mind Products
    I would be quite surprised if the NSA (National Security Agency)
    did not have a computer program to scan bits of shredded
    documents and electronically put them back together like a giant
    jigsaw puzzle. This suggests you cannot just shred, you must also burn.
    Roedy Green, May 28, 2012
  6. Jason Kim

    Lew Guest

    Get used to declaring top-level classes 'public':

    public class VolcanoApplication

    Once in a while you don't, but really almost never.

    (The top-level class is the one whose name matches the file name.)
    As you have learned, the "javac" compiler is smart enough to recognize the
    reference to 'VolcanoRobot' and hunt down the source or class.

    You absolutely do have to give the compiler some help. This help comes in two
    forms: "sourcepath" and "classpath". (The JVM runner, "java", also knows about

    In your case, without any other specification, both paths by default are ".",
    that means the current directory.

    So when the compiler hunts the classpath, it looks in the current directory.
    The first time it does not find "VolcanoRobot.class" in the classpath, so it
    hunts for "" in the sourcepath. In your case, it found it
    there, compiled it, then used the resulting "VolcanoRobot.class" in the classpath.

    Next time you compile, if you have made no source changes that are newer than
    the class files, it will skip the step.

    If you compile just 'VolcanoApplication', and there are no newer changes to
    'VolcanoRobot' the compiler will find the class file and be happy. If the
    source is newer, the compiler will recompile "", then find
    the class file and be happy.

    That is not always correct, only if the compiler can't find the source or if
    the change is limited to compile-time constants.
    "Note: Classes found through the classpath may be subject to automatic
    recompilation if their sources are also found. See Searching For Types."
    Never give yourself such an excuse to defer learning.

    How do you know, as a self-admitted beginner, what you do and do not need to

    As it happens, understanding how the compiler and JVM invoker work are among
    the very first and most important things you should learn. It isn't about
    whether what you do will be "crazy complicated", or even slightly complicated,
    or even dog simple. It's about whether you can do anything at all.


    P.S., Don't quote sigs.
    Lew, May 28, 2012
  7. Lew:

    Did I mis-remember that or has it changed since version 4 or there
    abouts? I seem to remember a long thread here on this subject and I've
    always erased all my .class files before every compilation to avoid it.
    Have I generated my own myth?
    Knute Johnson, May 28, 2012
  8. Jason Kim

    Roedy Green Guest

    There is a gotcha.
    If have a static final constant X in class A.

    Class B references X.

    You modify the value of X.

    The compeller will be smart enough to recompile A, but not B. It
    should recompile B, because of constant inlining.

    When you update non-private constant values, do a clean compile of
    everything to get the inlined constant values propagated.

    Roedy Green Canadian Mind Products
    Controlling complexity is the essence of computer programming.
    ~ Brian W. Kernighan 1942-01-01
    Roedy Green, May 28, 2012
  9. On Sun, 27 May 2012 21:08:29 -0700, Knute Johnson

    Maybe, but I can believe you had a difficulty that needed clean

    I had a problem with jCreator where I was using code from a
    textbook on an assignment. (Many of the exercises used textbook
    source code.) I had to compile the textbook source code, but then
    subsequent compilations would fail claiming that the textbook source
    code was not valid Java code! The solution^Whorrible kludge was to
    the delete the textbook source code used after the first compilation.

    When things like this happen, I am not surprised that people get
    shy. I prefer clean, full compiles myself.


    Gene Wirchenko
    Gene Wirchenko, May 28, 2012
  10. Jason Kim

    Lew Guest

    I live in the now. I don't know what you remember, nor how well, nor what changed.
    Or put it in it own JAR.

    Or figure out why it went wrong and solve it from understanding.
    The Java compiler does the best it can to resolve dependencies. It can't cover
    a lot of scenarios, and it can really lose it over sometimes having source in
    the sourcepath and sometimes not. It treats constants (as the JLS defines
    them) differently from other immutable or mutable expressions.

    Clean compiles are fine for your non-library (not in JARs) code and sometimes
    necessary. We're not supposed to behave by superstition, but clean compile is
    a prevalent and fairly harmless one.

    Better protection is to organize your code into JARs, where you never compile
    upstream JARs except when you work on their projects explicitly.

    I espouse full knowledge of the rules, but I struggle to stay up on the corner
    cases myself. I keep returning to study them, and discussions like this one
    help to elucidate them.

    For dependencies beyond what javac can handle, we have Ant. That why we have Ant.

    I am jaundiced by project after project after project where I've stepped in
    the build mess left by predecessors who created build systems by cult ritual.
    One of the worst was a "refactoring" of the build consigned to a contract
    company that claimed great expertise and tangled the ball of yarn even
    further. (That one used Maven, which complicated the repair process.)

    Build and deployment procedures require even more professionalism, diligence
    and attention to detail than program code.
    Lew, May 29, 2012
  11. Jason Kim

    Lew Guest

    I think it applies to instance and local constants also.

    What do you mean by that?

    The constant, by virtue of it being a constant, is in the B class as a
    constant. It is not a reference because it's a constant. Class B has no way of
    knowing that the constant once had a label in another class. Because it's a

    That's the way it is. I do not express an opinion on how it should be.

    The JLS does explain why that is, though.
    We create non-private constants, but we really aren't supposed to.
    "Other than for true mathematical constants, we recommend that source code
    make very sparing use of class variables that are declared static and final.
    If the read-only nature of final is required, a better choice is to declare a
    private static variable and a suitable accessor method to get its value."

    BTW, public, don't confuse constants with "static final" variables. Only some
    of the latter are the former, and some of the former are not the latter. The
    JLS doesn't restrict the definition of "constant variable" to static
    variables, or even member variables.
    "A variable of primitive type or type _String_, that is _final_ and
    initialized with a compile-time constant expression (§15.28), is called a
    /constant variable/."

    One of the implications:
    "One other thing to note is that static final fields that have constant values
    (whether of primitive or String type) must never appear to have the default
    initial value for their type (§4.12.5). This means that all such fields appear
    to be initialized first during class initialization (§, §9.3.1, §12.4.2)."
    [op. cit.]
    Lew, May 29, 2012
  12. Easy to say. Not necessarily easy to do.

    The error message was quite misleading. The solution was by
    accident. There was nothing that I could see that would help me in
    tracking down the cause of the problem.

    While I do like solving problems, sometimes, there is no clean

    This still fits.
    Well, it sure seems to have done that here.
    It does remove the problem of loss of synchronisation.



    Gene Wirchenko
    Gene Wirchenko, May 29, 2012
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.