JDK-6550655 : com.sun.tools.javac.code.Symbol$CompletionFailure
  • Type: Bug
  • Status: Closed
  • Resolution: Fixed
  • Component: tools
  • Sub-Component: javac
  • Priority: P3
  • Affected Version: 6
  • OS: windows_xp
  • CPU: x86
  • Submit Date: 2007-04-26
  • Updated Date: 2011-05-17
  • Resolved Date: 2011-05-17
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
JDK 7
7 b142Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Compiler error when compiling a class alone that depends on another class, which has already been compiled and has a dependency on a class from persistence-api.jar

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute the following batch file:

cls
del *.class
rem set javac="C:\bea\jdk150_06\bin\javac"
set javac="C:\Program Files\Java\jdk1.6.0_01\bin\javac"
set jpa=C:\soft\javalib\maven2\local-repository\javax\persistence\persistence-api\1.0\persistence-api-1.0.jar
set classpath=%jpa%
%javac% AccountingContextEty.java
set classpath=.
%javac% CompletionFailureTest.java

The problem occurs as well with java5, but not one the same class:

C:\tmp\CompletionFailure>"C:\bea\jdk150_06\bin\javac" CompletionFailureTest.java
An exception has occurred in the compiler (1.5.0_06). Please file a bug at the Java Developer Connection (http://java.sun.com/webapp
com.sun.tools.javac.code.Symbol$CompletionFailure: file javax\persistence\Temporal.class not found

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
correct compilation without any warning or errors
ACTUAL -
.\AccountingContextEty.class: warning: Cannot find annotation method 'value()' in type 'javax.persistence.Temporal': class file for javax.persistence.Temporal not found
An exception has occurred in the compiler (1.6.0_01). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
com.sun.tools.javac.code.Symbol$CompletionFailure: class file for javax.persistence.TemporalType not found


ERROR MESSAGES/STACK TRACES THAT OCCUR :
see actual results

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.persistence.Table;

import java.util.Date;

import javax.persistence.Temporal;
import javax.persistence.TemporalType;

public class AccountingContextEty {
    @Temporal(TemporalType.DATE)
    private Date currentAccountingDate;
}

---------------------------------------------------------

public class CompletionFailureTest {
	AccountingContextEty ety;
}

---------- END SOURCE ----------
Here is the easily reproducible test case.
% cat genbug
#!/bin/bash

if [ "x$1" != "x" ]; then
  export JAVA_HOME=$1
fi

Ejava() {
(
  printf "public enum E {NORTH,SOUTH,EAST,WEST}\n"
) > E.java
}

Ijava() {
(
  printf "import java.lang.annotation.*;\n"
  printf "@Target(ElementType.FIELD)\n"
  printf "@Retention(RetentionPolicy.RUNTIME)\n"
  printf "    public @interface I {E value();\n"
  printf "}\n"
) > I.java
}

Cjava() {
(
  printf "public class C {\n"
  printf "    @I(E.NORTH) public String s;\n"
  printf "}\n"
) > C.java
}

Djava() {
(
  printf "public class D {C c;}\n"
) > D.java
}

rm -f *.java *.class
Ejava
Ijava
Cjava
Djava

$JAVA_HOME/bin/javac -version
$JAVA_HOME/bin/javac E.java I.java C.java
rm E.java E.class
$JAVA_HOME/bin/javac D.java

% ./genbug /usr/jdk/instances/jdk1.6.0
javac 1.6.0_07
An exception has occurred in the compiler (1.6.0_07). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
com.sun.tools.javac.code.Symbol$CompletionFailure: class file for E not found
Reported while trying to use annotations in NetBeans development:

http://www.netbeans.org/nonav/issues/show_bug.cgi?id=152562


Simple test case, a bit different from those shown already:


package a;
public @interface A {
    E e();
    enum E {V1, V2}
}

package b;
@a.A(e=a.A.E.V1)
public @interface B {}

package c;
@b.B
public class C {}


Compile B.java against A.class, and C.java against B.class but not A.class. The compiler reports:

/tmp/test152562/b/dist/b.jar(b/B.class): warning: Cannot find annotation method 'e()' in type 'a.A': class file for a.A not found
An exception has occurred in the compiler (1.6.0_10). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
com.sun.tools.javac.code.Symbol$CompletionFailure: class file for a.A$E not found

Clearly the compiler should not crash, but I also think it should not treat this as an error in user code. See bug #6365854 for justification:

"There doesn't seem to be any problems allowing the program to compile without the annotations. After the fix, the compiler will accept the program but issue a warning.  The rationale is that the missing annotation can cause problems when running the program."

This case seems very similar. The @A annotation in B.class cannot be resolved, but that should not prevent C.java from being compiled. The only difference here is that an enum in that annotation also cannot be resolved.
I should add that it would be better for javac to not even issue a warning in case the intermediate annotation (B in my last example) has only CLASS retention: there is no danger of the compiled class (here, C) failing to link at runtime. A warning would be appropriate in case B had RUNTIME retention.

Comments
SUGGESTED FIX A webrev of this fix is available at the following URL: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/dc3d9ef880a1
2011-04-29

EVALUATION This is how we should fix this: *) If a completion failure is thrown when entering an annotation through Annotate, a resolution diagnostic is issued - it means that some symbol could not be found. *) If a completion failure is thrown when entering an annotation through ClassReader, a **warning** is issued. Compilation will succeed and eventually lead to ClassNotFoundError when the code is executed (only if annotation had a runtime retain policy). This policy seems in sync with what I've been able to infer by looking at the class reader code; it seems like javac is meant to be tolerant w.r.t. problems found in annotations when reading from class files and strict when the same problems are encountered in the source file - and I can see why this policy makes sense.
2011-04-29

SUGGESTED FIX As mentioned in Description, I do not think this should be treated as a fatal error. diff --git a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1377,6 +1377,7 @@ // type.tsym.flatName() should == proxy.enumFlatName TypeSymbol enumTypeSym = proxy.enumType.tsym; VarSymbol enumerator = null; + try { for (Scope.Entry e = enumTypeSym.members().lookup(proxy.enumerator); e.scope != null; e = e.next()) { @@ -1384,6 +1385,9 @@ enumerator = (VarSymbol)e.sym; break; } + } + } catch (CompletionFailure failure) { + return; // ignore } if (enumerator == null) { log.error("unknown.enum.constant", results in just /tmp/test152562/b/dist/b.jar(b/B.class): warning: Cannot find annotation method 'e()' in type 'a.A': class file for a.A not found but C.java is successfully compiled, and C.class correctly seems to contain the @B annotation. Probably some added warning is in order in case A.class could be found but A$E.class could not. See also bug #6400041.
2008-11-24

SUGGESTED FIX diff --git a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1390,17 +1390,26 @@ public class ClassReader extends ClassFi // type.tsym.flatName() should == proxy.enumFlatName TypeSymbol enumTypeSym = proxy.enumType.tsym; VarSymbol enumerator = null; - for (Scope.Entry e = enumTypeSym.members().lookup(proxy.enumerator); - e.scope != null; - e = e.next()) { - if (e.sym.kind == VAR) { - enumerator = (VarSymbol)e.sym; - break; + CompletionFailure failure = null; + try { + for (Scope.Entry e = enumTypeSym.members().lookup(proxy.enumerator); + e.scope != null; + e = e.next()) { + if (e.sym.kind == VAR) { + enumerator = (VarSymbol)e.sym; + break; + } } + } catch (CompletionFailure cf) { + failure = cf; } if (enumerator == null) { - log.error("unknown.enum.constant", - currentClassFile, enumTypeSym, proxy.enumerator); + if (failure != null) { + log.error("proc.messager", failure.getMessage()); + } else { + log.error("unknown.enum.constant", + currentClassFile, enumTypeSym, proxy.enumerator); + } result = new Attribute.Error(enumTypeSym.type); } else { result = new Attribute.Enum(enumTypeSym.type, enumerator);
2008-05-22

EVALUATION Sure enough the class is missing or atleast it is not on the classpath. It it were not to be an Class required by annotation a similar kind of scenario would have a created ClassNotFoundException at runtime. Needs to dealt with from a compiler stand point and give some user friendly diagnostics rather than the current output which is not acceptable.
2008-05-03

EVALUATION Could reproduce the bug will look into it now.
2008-04-30

EVALUATION Please provide a small self-contained reproducible test case.
2007-05-15