RFR: timestamp oddities -sourcepath vs zip/jar
Jonathan Gibbons
jonathan.gibbons at oracle.com
Tue Sep 24 07:29:10 PDT 2013
Fredrik,
It is a misconfiguration to have classes on the sourcepath, with
corresponding classes in the compiled classes directory, AND in rt.jar.
If you're compiling the core JDK classes, you should make sure that
rt.jar is not on the classpath or bootclasspath. For example, you
should put sources on the source path and then set the bootclasspath to
the compiled classes directory. This is how the "old build" worked,
successfully, for many years.
Although the situation you are describing is specific to the JDK build,
the general recommendation still applies: don't put a zip file on the
class path containing compiled classes for any sources you are compiling.
-- Jon
On 09/23/2013 10:40 PM, Fredrik Öhrström wrote:
> It is a serious bug that command line javac can behave in two
> different ways when given completely static and predictable source code.
> Especially since the change in behavior comes from timestamps inside
> rt.jar, which a normal user has no control of, nor can easily see.
>
> The intent of the timestamp compare is to know if the class file is
> out of date in respect to the source file.
> Thus if the source has been changed then recompile and write the
> class. Now the class is up to date.
> However a class inside a jar file and >especially< inside rt.jar is
> completely outside of this loop and
> should only be used when there is no class file in bin, nor any source
> file in src. Only the timestamp
> of classes in bin, that can actually be affected by recompilation
> should matter.
>
> As I said, there are several ways to fix this. Another way would be to
> exclude rt.jar from the comparison.
> -Xprefer:source is not good enough because it will recompile
> everything indiscriminately on the sourcepath
> even though the class has already been compiled and exists in bin.
>
> Thus preferredFileObject is faulty by design and has managed to stay
> that way since
> not may people have exercised -sourcepath, especially not when
> building classes that
> also exist in rt.jar.
>
> //Fredrik
>
>
>
> 2013/9/23 Jonathan Gibbons <jonathan.gibbons at oracle.com
> <mailto:jonathan.gibbons at oracle.com>>
>
> On 09/22/2013 06:41 AM, Fredrik Öhrström wrote:
>
> The preferredFileObject test in ClassReader.java does cause
> confusion when timestamps inside zip files are too new.
>
> Lets say that you have in src/alfa/A.java
> public class A { void a() { java.lang.Object.foo = 42; } }
> and in src/java/lang/Object.java
> public class Object { public static int foo; }
>
> You can now always compile using the following command:
> javac -d bin src/alfa/A.java src/java/lang/Object.java
>
> But you can only >>sometimes<< compile using the following
> command:
> javac -d bin -sourcepath src src/alfa/A.java
>
> When it fails, javac has picked up java.lang.Object from
> rt.jar and
> not from the sourcepath. This happens when the timestamp
> inside rt.jar
> is newer than the source file.
>
> The net result is that when compiling the OpenJDK with
> --enable-sjavac
> everything works fine, then you upgrade your jdk and the
> compilation
> fails in very weird ways. And will fail until you touch all
> your source files.
>
> There are several ways to fix this, but all require some thought.
> However a simple fix, would be to ignore the timestamps of
> class files
> inside zip/jars because they probably do not mean anything
> important....
>
> Thus in preferredFileObject, if b is a ZipFileIndexFileObject,
> then use the source!
> protected JavaFileObject preferredFileObject(JavaFileObject a,
> JavaFileObject b) {
> if (preferSource)
> return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a
> : b;
> else {
> if (b instanceof
> com.sun.tools.javac.file.ZipFileIndexArchive.ZipFileIndexFileObject)
> {
> return a;
> }
> long adate = a.getLastModified();
> long bdate = b.getLastModified();
> // 6449326: policy for bad lastModifiedTime in ClassReader
> //assert adate >= 0 && bdate >= 0;
> return (adate > bdate) ? a : b;
> }
> }
>
> What do you think?
>
> //Fredrik
>
>
>
>
>
> Fredrik,
>
> There is no guarantee that items in zip files are presented to
> javac in the class you test for, so the instanceof test is highly
> suspicious and likely to be a source of inconsistent behavior.
> For example, what happens if someone using using javac via the
> CompilerAPI (JSR 199) and provides their own custom file manager?
>
> If you want to make sure you're compiling source code, use
> -Xprefer:source. Or, keep your timestamps straight.
>
> -- Jon
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20130924/8c303bec/attachment-0001.html
More information about the compiler-dev
mailing list