JDK-5011101 : (main) Premature generation of class file fools javac dependency checker later
  • Type: Enhancement
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P4
  • Status: Resolved
  • Resolution: Won't Fix
  • OS: linux
  • CPU: x86
  • Submitted: 2004-03-10
  • Updated: 2022-05-17
  • Resolved: 2022-05-17
Related Reports
Relates :  
Relates :  
Description
Name: jl125535			Date: 03/10/2004


FULL PRODUCT VERSION :
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)

java version "1.5.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta2-b41)
Java HotSpot(TM) Client VM (build 1.5.0-beta2-b41, mixed mode)

A DESCRIPTION OF THE PROBLEM :
Given these files:

BadFile.java (will not compile):

 public class BadFile {
     static TestFile test;

     static public void main(String args[]) {
         throw new java.io.IOException();
     }
 }

TestFile.java:

 public class TestFile extends BadFile {
    static OtherClass other;
    static OtherPublic other2;
 }

 class OtherClass extends BadFile { }

OtherPublic.java:

 public class OtherPublic { }

The command "javac TestFile.java OtherPublic.java BadFile.java" will generate TestFile.class and nothing else. This means that TestFile.class is now newer than TestFile.java, so if the error is removed from BadFile.java and only BadFile is recompiled ("javac BadFile.java"), OtherClass.class will not be generated, even though it is required and would be generated if TestFile.class had not been generated. Furthermore, OtherPublic.class is also not generated in this situation, even though it, too, is required by TestFile and would normally be generated.

This causes a similar problem with ant, which has no idea that there are missing  non-public classes, although ant will recompile any file whose public class has not been generated, so it does not lack OtherPublic.class

Note that this does not happen if the error is an import not found or a syntax error.

STEPS TO REPRODUCE BEHAVIOR :
1. javac TestFile.java OtherPublic.java BadFile.java
2. Correct the mistake in BadFile.java
3. javac BadFile.java

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TestFile.class should not be generated by step 1.

A public class file should only be generated if it would lead to the correct behaviour of the javac dependency checking mechanism: all of the classes which it depends on have been generated, and all of the classes in the same source file have been generated.

ACTUAL -
TestFile.class is generated by step 1.

REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER SUBMITTED WORKAROUND :
If all .class files are removed or all source files are listed on the javac command line, the next build will be correct (but slow).

If make is used with a sufficiently clever tool to determine the dependencies (e.g., gcj), it is possible to get conservative builds which are correct.
(Incident Review ID: 185671) 
======================================================================
###@###.### 10/26/04 06:06 GMT

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
17-09-2004

EVALUATION Your dependency checker is apparently now powerful enough to handle source files that contain multiple top-level classes. Until you get a better dependency checker, I suggest you stop doing that. On the second compile in your scenario, the compiler is compiling the source named on the command line successfully. javac has no way to know that there is some class somewhere else that you would also like compiled. Having said all that, it is indeed possible for javac to complete semantic analysis of a translation unit before emitting any of its code. ###@###.### 2004-03-10 I don't think javac should generate class files until a compilation unit has completed semantic analysis. ###@###.### 2004-09-06
10-03-2004