JDK-8187422 : javadoc errors if invalid source files coexist with documented source files
  • Type: Bug
  • Component: tools
  • Sub-Component: javadoc(tool)
  • Affected Version: 9
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: x86_64
  • Submitted: 2017-09-08
  • Updated: 2018-10-23
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 Availability Release.

To download the current JDK release, click here.
Other
tbd_minorUnresolved
Related Reports
Blocks :  
Duplicate :  
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
openjdk version "9-Ubuntu"
OpenJDK Runtime Environment (build 9-Ubuntu+0-9b181-4)
OpenJDK 64-Bit Server VM (build 9-Ubuntu+0-9b181-4, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux astoria 4.10.0-32-generic #36-Ubuntu SMP Tue Aug 8 12:10:06 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
javadoc has started validating source files that it shouldn't be reading. If these are invalid, then javadoc crashes with an exception. This is unexpected, and a regression from Java 8.

With source files in a layout like the following, where "Valid" is a valid Java source file, and "Invalid.java" is an invalid Java source file:

com/example/Valid.java
com/example/Invalid.java

... running "javadoc com/example/Valid.java" used to succeed, but now fails with a big exception, starting with:

javadoc: error - An exception occurred while building a component: Contents
	(com.sun.tools.javac.code.ClassFinder$BadClassFile: bad source file: ./com/example/Invalid.java
  file does not contain class com.example.Invalid


This happens when people litter test or example code around, e.g. Invalid.java contains:

/* no package line */
class Invalid {}


REGRESSION.  Last worked in version 8u131

ADDITIONAL REGRESSION INFORMATION: 
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11)
OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
# This bash script creates some source files:

mkdir -p a

# first, a valid class:
echo 'package a; public class B {}' > a/B.java

# then, an invalid one:
echo '/* no package */ class RealClassName {}' > a/RealFileName.java

# and tries to generate the javadoc for just the valid class:
javadoc a/B.java


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
On Java 8, the invalid files are ignored; the doc is generated for just "B".

ACTUAL -
On Java 9, javadoc fails, and the big exception is output.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
javadoc: error - An exception occurred while building a component: Contents
	(com.sun.tools.javac.code.ClassFinder$BadClassFile: bad source file: ./a/C.java
  file does not contain class a.C
  Please remove or make sure it appears in the correct subdirectory of the sourcepath.)
Please file a bug against the javadoc tool via the Java bug reporting page
(http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com)
for duplicates. Include error messages and the following diagnostic in your report. Thank you.
com.sun.tools.javac.code.ClassFinder$BadClassFile: bad source file: ./a/C.java
  file does not contain class a.C
  Please remove or make sure it appears in the correct subdirectory of the sourcepath.
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.readSourceFile(JavaCompiler.java:856)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.readSourceFile(JavaCompiler.java:783)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.lambda$new$0(JavaCompiler.java:343)
	at jdk.compiler/com.sun.tools.javac.code.ClassFinder.fillIn(ClassFinder.java:352)
	at jdk.compiler/com.sun.tools.javac.code.ClassFinder.complete(ClassFinder.java:285)
	at jdk.compiler/com.sun.tools.javac.code.Symbol.complete(Symbol.java:633)
	at jdk.compiler/com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:1314)
	at jdk.compiler/com.sun.tools.javac.code.Symbol$ClassSymbol.flags(Symbol.java:1248)
	at jdk.compiler/com.sun.tools.javac.code.Symbol$TypeSymbol.getEnclosedElements(Symbol.java:800)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getItems0(Utils.java:2468)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getItems0(Utils.java:2463)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.recursiveGetItems(Utils.java:2451)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils$16.visitPackage(Utils.java:2436)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils$16.visitPackage(Utils.java:2432)
	at jdk.compiler/com.sun.tools.javac.code.Symbol$PackageSymbol.accept(Symbol.java:1166)
	at java.compiler@9-Ubuntu/javax.lang.model.util.AbstractElementVisitor6.visit(AbstractElementVisitor6.java:106)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getItems(Utils.java:2445)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getClasses(Utils.java:2182)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getAllClasses(Utils.java:2355)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.hasConstantField(ConstantsSummaryBuilder.java:258)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.buildContents(ConstantsSummaryBuilder.java:171)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder.build(AbstractBuilder.java:157)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder.buildChildren(AbstractBuilder.java:200)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.buildConstantSummary(ConstantsSummaryBuilder.java:156)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder.build(AbstractBuilder.java:157)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.build(ConstantsSummaryBuilder.java:136)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.AbstractDoclet.generateOtherFiles(AbstractDoclet.java:228)
	at jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.HtmlDoclet.generateOtherFiles(HtmlDoclet.java:116)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.AbstractDoclet.startGeneration(AbstractDoclet.java:213)
	at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.AbstractDoclet.run(AbstractDoclet.java:117)
	at jdk.javadoc/jdk.javadoc.doclet.StandardDoclet.run(StandardDoclet.java:72)
	at jdk.javadoc/jdk.javadoc.internal.tool.Start.parseAndExecute(Start.java:574)
	at jdk.javadoc/jdk.javadoc.internal.tool.Start.begin(Start.java:423)
	at jdk.javadoc/jdk.javadoc.internal.tool.Start.begin(Start.java:340)
	at jdk.javadoc/jdk.javadoc.internal.tool.Main.execute(Main.java:63)
	at jdk.javadoc/jdk.javadoc.internal.tool.Main.main(Main.java:52)
1 error


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
See "steps to reproduce".
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Teach the build system to remove the example classes from the source tree before building?


Comments
There is really nothing needed for javadoc, other than maybe have the above test, and make sure javadoc/doclet copes with ErrorType returned by javac.
04-12-2017

The problem here is that javac throws the .ClassFinder$BadClassFile which is a type of CompletetionFailure and RuntimeException, and the trouble is the exception is caught by the Doclet when invoking Element.getEnclosingElements(..), this should not be throwing an Exception according to API spec. Therefore this API needs to be changed or perhaps specify that ErrorElement could be returned, in which case javac needs to trap these and insert an ErrorElement into the returned list. Reproducer and a doit script ====XX/a/B.java==== package a; public class B{} ====XX/a/C.java==== public class C{} ======== % cat doit -d XX/foo.out -sourcepath XX XX/a/B.java % javadoc @doit
23-09-2017

The stacktrace does contain text describing the underlying problem bad source file: ./a/C.java file does not contain class a.C
19-09-2017

Bad sources and class-files are no longer allowed with javadoc, this is by design and not a regression, please see https://bugs.openjdk.java.net/browse/JDK-8176535 However javadoc should not crash with an exception but exit gracefully with a user friendly error such as "Error: Foo.java is an invalid input file" or something.
11-09-2017

javadoc should not crash, so that needs to be fixed, but users should not mix invalid test code with real classes on the javadoc command line.
11-09-2017

Created 2 simple files under directory a/ B.java == package a; public class B {} == C.java ==No package information public class C {} == # and tries to generate the javadoc for just the valid class: javadoc a/B.java Issue is reproducible only on 9, test passes in 8u144 and 8u152 9 ea b181 == javadoc: error - An exception occurred while building a component: Contents (com.sun.tools.javac.code.ClassFinder$BadClassFile: bad source file: ./a/C.java file does not contain class a.C Please remove or make sure it appears in the correct subdirectory of the sourcepath.) Please file a bug against the javadoc tool via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include error messages and the following diagnostic in your report. Thank you. com.sun.tools.javac.code.ClassFinder$BadClassFile: bad source file: ./a/C.java file does not contain class a.C Please remove or make sure it appears in the correct subdirectory of the sourcepath. at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.readSourceFile(JavaCompiler.java:856) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.readSourceFile(JavaCompiler.java:783) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.lambda$new$0(JavaCompiler.java:343) at jdk.compiler/com.sun.tools.javac.code.ClassFinder.fillIn(ClassFinder.java:352) at jdk.compiler/com.sun.tools.javac.code.ClassFinder.complete(ClassFinder.java:285) at jdk.compiler/com.sun.tools.javac.code.Symbol.complete(Symbol.java:633) at jdk.compiler/com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:1314) at jdk.compiler/com.sun.tools.javac.code.Symbol$ClassSymbol.flags(Symbol.java:1248) at jdk.compiler/com.sun.tools.javac.code.Symbol$TypeSymbol.getEnclosedElements(Symbol.java:800) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getItems0(Utils.java:2468) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getItems0(Utils.java:2463) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.recursiveGetItems(Utils.java:2451) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils$16.visitPackage(Utils.java:2436) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils$16.visitPackage(Utils.java:2432) at jdk.compiler/com.sun.tools.javac.code.Symbol$PackageSymbol.accept(Symbol.java:1166) at java.compiler@9/javax.lang.model.util.AbstractElementVisitor6.visit(AbstractElementVisitor6.java:106) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getItems(Utils.java:2445) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getClasses(Utils.java:2182) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.util.Utils.getAllClasses(Utils.java:2355) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.hasConstantField(ConstantsSummaryBuilder.java:258) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.buildContents(ConstantsSummaryBuilder.java:171) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder.build(AbstractBuilder.java:157) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder.buildChildren(AbstractBuilder.java:200) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.buildConstantSummary(ConstantsSummaryBuilder.java:156) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder.build(AbstractBuilder.java:157) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.build(ConstantsSummaryBuilder.java:136) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.AbstractDoclet.generateOtherFiles(AbstractDoclet.java:228) at jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.HtmlDoclet.generateOtherFiles(HtmlDoclet.java:116) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.AbstractDoclet.startGeneration(AbstractDoclet.java:213) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.AbstractDoclet.run(AbstractDoclet.java:117) at jdk.javadoc/jdk.javadoc.doclet.StandardDoclet.run(StandardDoclet.java:72) at jdk.javadoc/jdk.javadoc.internal.tool.Start.parseAndExecute(Start.java:574) at jdk.javadoc/jdk.javadoc.internal.tool.Start.begin(Start.java:423) at jdk.javadoc/jdk.javadoc.internal.tool.Start.begin(Start.java:340) at jdk.javadoc/jdk.javadoc.internal.tool.Main.execute(Main.java:63) at jdk.javadoc/jdk.javadoc.internal.tool.Main.main(Main.java:52) 1 error
11-09-2017