Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Java dependency on a constant lead to recompilation?

Tags:

java

ant

I have a couple of simple classes:

// src/Consts.java
public class Consts
{
    public static final int A = 100;
    public static final int B = 101;
}

And:

// src/Print.java
public class Print
{
    public static void main(String[] args)
    {
        System.out.println("A: " + Consts.A + " B: " + Consts.B);
    }
}

I have a simple ant build file:

<project name="Test" default="compile" basedir=".">
  <!-- set global properties for this build -->
  <property name="src" location="src"/>
  <property name="build" location="build"/>

  <target name="compile">
    <mkdir dir="${build}"/>
    <!-- Compile the java code from ${src} into ${build} -->
    <javac srcdir="${src}" destdir="${build}" debug="on" />
  </target>

  <target name="clean">
    <delete dir="${build}"/>
  </target>
</project>

I run ant, then run java -cp build Print, I get the output I expect, A: 100, B: 101. Fine. Then I edit Consts.java to set A = 200 and B = 201 and re-run ant. It says "Compiling 1 source file", which is Consts.java (confirmed by looking at time-stamps of class files). Then I re-run java -cp build Print and it prints A: 100, B: 101. Which was unexpected, to say the least.

Googling suggests that the values from Consts are substituted at compile-time into the Print source. Which is fine, but my question then is: why did ant+javac not recompile Print when Consts changed? There is a clear compile-time dependency between the two.

(I just got bit so hard by this issue and it seems to me it is surely a bug in one of the tools. Or am I missing something?)

like image 348
Neil Brown Avatar asked Nov 02 '16 10:11

Neil Brown


1 Answers

Having looked around a bit further after seeing Andy Turner's link, I think ant is just much dumber than I thought it would be. From the javac task:

Note: Apache Ant uses only the names of the source and class files to find the classes that need a rebuild. It will not scan the source and therefore will have no knowledge about nested classes, classes that are named different from the source file, and so on. See the task for dependency checking based on other than just existence/modification times.

The mentioned depend task even says this explicitly:

The most obvious example of these limitations is that the task can't tell which classes to recompile when a constant primitive data type exported by other classes is changed. For example, a change in the definition of something like

public final class Constants { public final static boolean DEBUG=false; }

will not be picked up by other classes.

Which seems to describe my case exactly. I think the lesson in all this for me is: (a) don't use ant, (b) if you do, always clean before a build.

like image 139
Neil Brown Avatar answered Oct 14 '22 12:10

Neil Brown