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.

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

    dante.showAttributes();
    System.out.println("Increasing speed to 3.");
    dante.speed = 3;
    dante.showAttributes();
    System.out.println("Changing temperature to 670");
    dante.temperature = 670;
    dante.showAttributes();
    System.out.println("Checking the temperature.");
    dante.checkTemperatur();
    dante.showAttributes();
    }
    }

    VolcanoRobot.java
    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 VolcanoApplication.java

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

  2. On 5/27/2012 3:48 PM, Jason Kim wrote:
    > I am new to Java.
    >
    > Here are two files.
    >
    > VolcanoApplication.java
    > class VolcanoApplication {
    > public static void main(String[] arguments) {
    > VolcanoRobot dante = new VolcanoRobot();
    > dante.status = "exploring";
    > dante.speed = 2;
    > dante.temperature = 510;
    >
    > dante.showAttributes();
    > System.out.println("Increasing speed to 3.");
    > dante.speed = 3;
    > dante.showAttributes();
    > System.out.println("Changing temperature to 670");
    > dante.temperature = 670;
    > dante.showAttributes();
    > System.out.println("Checking the temperature.");
    > dante.checkTemperatur();
    > dante.showAttributes();
    > }
    > }
    >
    > VolcanoRobot.java
    > 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 VolcanoApplication.java
    >
    > But how does Java know that VolcanoRobot.java should also be in the compilation?


    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 VolcanoRobot.java even if it has changed since the
    VolcanoRobot.class file was created.

    --

    Knute Johnson
     
    Knute Johnson, May 28, 2012
    #2
    1. Advertising

  3. Jason Kim

    Jason Kim Guest

    On Sunday, 27 May 2012 19:34:42 UTC-4, Knute Johnson wrote:
    > On 5/27/2012 3:48 PM, Jason Kim wrote:
    > > I am new to Java.
    > >
    > > Here are two files.
    > >
    > > VolcanoApplication.java
    > > class VolcanoApplication {
    > > public static void main(String[] arguments) {
    > > VolcanoRobot dante = new VolcanoRobot();
    > > dante.status = "exploring";
    > > dante.speed = 2;
    > > dante.temperature = 510;
    > >
    > > dante.showAttributes();
    > > System.out.println("Increasing speed to 3.");
    > > dante.speed = 3;
    > > dante.showAttributes();
    > > System.out.println("Changing temperature to 670");
    > > dante.temperature = 670;
    > > dante.showAttributes();
    > > System.out.println("Checking the temperature.");
    > > dante.checkTemperatur();
    > > dante.showAttributes();
    > > }
    > > }
    > >
    > > VolcanoRobot.java
    > > 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 VolcanoApplication.java
    > >
    > > But how does Java know that VolcanoRobot.java should also be in the compilation?

    >
    > 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 VolcanoRobot.java even if it has changed since the
    > VolcanoRobot.class file was created.
    >
    > --
    >
    > Knute Johnson


    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
    #3
  4. Jason Kim

    Roedy Green Guest

    On Sun, 27 May 2012 15:48:01 -0700 (PDT), Jason Kim
    <> wrote, quoted or indirectly quoted someone who
    said :

    >But how does Java know that VolcanoRobot.java should also be in the compilation?


    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
    compile.

    3. It can compare the dates on the class file and corresponding *.java
    file. If the *.java file is newer it knows to recompile.
    see http://mindprod.com/jgloss/javac.html

    4. Use ANT. See http://mindprod.com/jgloss/ant.html
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com
    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
    #4
  5. Jason Kim

    Roedy Green Guest

    On Sun, 27 May 2012 17:35:05 -0700, Roedy Green
    <> wrote, quoted or indirectly quoted
    someone who said :

    >3. It can compare the dates on the class file and corresponding *.java
    >file. If the *.java file is newer it knows to recompile.
    >see http://mindprod.com/jgloss/javac.html


    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 http://mindprod.com/products1.html#JARCHECK 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
    http://mindprod.com
    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
  6. Jason Kim

    Lew Guest

    Jason Kim wrote:
    > Knute Johnson wrote:
    >> Jason Kim wrote:
    >>> I am new to Java.
    >>>
    >>> Here are two files.
    >>>
    >>> VolcanoApplication.java
    >>> class VolcanoApplication {


    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.)

    >>> public static void main(String[] arguments) {
    >>> VolcanoRobot dante = new VolcanoRobot();


    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
    "classpath".)

    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 "VolcanoRobot.java" 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 "VolcanoRobot.java", then find
    the class file and be happy.

    ....
    >>> }
    >>>
    >>> VolcanoRobot.java
    >>> class VolcanoRobot {
    >>> ...
    >>> }
    >>>
    >>> I compiled the program by doing
    >>> $ javac VolcanoApplication.java
    >>>
    >>> But how does Java know that VolcanoRobot.java should also be in the compilation?

    >>
    >> 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 VolcanoRobot.java even if it has changed since the
    >> VolcanoRobot.class file was created.


    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."
    <http://docs.oracle.com/javase/6/docs/technotes/tools/solaris/javac.html>

    > 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.


    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
    learn?

    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.

    <http://docs.oracle.com/javase/6/docs/technotes/tools/>

    P.S., Don't quote sigs.

    --
    Lew
    This is a sig (short for "signature"). It does not convey part of the main
    conversation. No need to quote it.
     
    Lew, May 28, 2012
    #6
  7. On 5/27/2012 8:18 PM, Lew wrote:
    > 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."
    > <http://docs.oracle.com/javase/6/docs/technotes/tools/solaris/javac.html>


    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
     
    Knute Johnson, May 28, 2012
    #7
  8. Jason Kim

    Roedy Green Guest

    On Sun, 27 May 2012 17:35:05 -0700, Roedy Green
    <> wrote, quoted or indirectly quoted
    someone who said :

    >3. It can compare the dates on the class file and corresponding *.java
    >file. If the *.java file is newer it knows to recompile.
    >see http://mindprod.com/jgloss/javac.html


    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
    http://mindprod.com
    Controlling complexity is the essence of computer programming.
    ~ Brian W. Kernighan 1942-01-01
    ..
     
    Roedy Green, May 28, 2012
    #8
  9. On Sun, 27 May 2012 21:08:29 -0700, Knute Johnson
    <> wrote:

    [snip]

    >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?


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

    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.

    Sincerely,

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

    Lew Guest

    Gene Wirchenko wrote:
    > Knute Johnson wrote:
    > [snip]
    >
    >> 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?


    I live in the now. I don't know what you remember, nor how well, nor what changed.

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


    +1

    > 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.


    Or put it in it own JAR.

    Or figure out why it went wrong and solve it from understanding.

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


    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


    --
    Lew
    Honi soit qui mal y pense.
    http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg
     
    Lew, May 29, 2012
    #10
  11. Jason Kim

    Lew Guest

    Roedy Green wrote:
    >> 3. It can compare the dates on the class file and corresponding *.java
    >> file. If the *.java file is newer it knows to recompile.
    >> see http://mindprod.com/jgloss/javac.html

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


    I think it applies to instance and local constants also.

    > 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.


    "Should"?

    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
    constant.

    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.

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


    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."
    <http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.9>

    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.
    <http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4>
    "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 (§8.3.2.1, §9.3.1, §12.4.2)."
    [op. cit.]

    --
    Lew
    Honi soit qui mal y pense.
    http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg
     
    Lew, May 29, 2012
    #11
  12. On Mon, 28 May 2012 22:35:41 -0700, Lew <> wrote:

    >Gene Wirchenko wrote:
    >> Knute Johnson wrote:
    >> [snip]
    >>
    >>> 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?

    >
    >I live in the now. I don't know what you remember, nor how well, nor what changed.
    >
    >> Maybe, but I can believe you had a difficulty that needed clean
    >> compiles.

    >
    >+1
    >
    >> 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.

    >
    >Or put it in it own JAR.
    >
    >Or figure out why it went wrong and solve it from understanding.


    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
    solution.

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


    This still fits.

    >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.


    Well, it sure seems to have done that here.

    >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.


    It does remove the problem of loss of synchronisation.

    [snip]

    Sincerely,

    Gene Wirchenko
     
    Gene Wirchenko, May 29, 2012
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?TW9yaQ==?=
    Replies:
    3
    Views:
    323
    Patrick.O.Ige
    Jan 18, 2006
  2. agent349
    Replies:
    12
    Views:
    485
    Mark A. Gibbs
    Apr 18, 2004
  3. Klaus Schneider
    Replies:
    1
    Views:
    576
    Rolf Magnus
    Dec 2, 2004
  4. Replies:
    4
    Views:
    984
    M.E.Farmer
    Feb 13, 2005
  5. lander
    Replies:
    5
    Views:
    617
    bruce barker
    Mar 5, 2008
Loading...

Share This Page