JDK-8224092 : ClassCastException when trying to use custom DocletEnvironment implementation
  • Type: Bug
  • Component: tools
  • Sub-Component: javadoc(tool)
  • Affected Version: 11,12,13
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2019-05-16
  • Updated: 2025-03-26
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
tbdUnresolved
Related Reports
Duplicate :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)

A DESCRIPTION OF THE PROBLEM :
When trying to customize the JavaDoc generation process by wrapping the original DocletEnvironment implementation, the JavaDoc generation fails with a ClassCastException, because the JDK attempts to cast to the "exact" type of the DocletEnvironment instance.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Write a custom doclet that extends the StandardDoclet and uses a delegate for DocletEnvironment and then use the doclet during JavaDoc generation.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The doclet works and no classcastexception is raised.
ACTUAL -
The Workarounds class attempts to cast the class to the default DocEnvImpl type and fails with a ClassCastException.

---------- BEGIN SOURCE ----------
package bug.demo;

import java.util.Set;

import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject.Kind;

import com.sun.source.util.DocTrees;

import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.StandardDoclet;

public class NewDoclet extends StandardDoclet {

    @Override
    public boolean run(DocletEnvironment docEnv) {
        return super.run(wrap(docEnv));
    }

    public DocletEnvironment wrap(DocletEnvironment env) {
        return new DocletEnvironment() {
            @Override
            public Set<? extends Element> getSpecifiedElements() {
                return env.getSpecifiedElements();
            }

            @Override
            public Set<? extends Element> getIncludedElements() {
                return env.getIncludedElements();
            }

            @Override
            public DocTrees getDocTrees() {
                return env.getDocTrees();
            }

            @Override
            public Elements getElementUtils() {
                return env.getElementUtils();
            }

            @Override
            public Types getTypeUtils() {
                return env.getTypeUtils();
            }

            @Override
            public boolean isIncluded(Element element) {
                return env.isIncluded(element);
            }

            @Override
            public boolean isSelected(Element element) {
                return env.isSelected(element);
            }

            @Override
            public JavaFileManager getJavaFileManager() {
                return env.getJavaFileManager();
            }

            @Override
            public SourceVersion getSourceVersion() {
                return env.getSourceVersion();
            }

            @Override
            public ModuleMode getModuleMode() {
                return env.getModuleMode();
            }

            @Override
            public Kind getFileKind(TypeElement type) {
                return env.getFileKind(type);
            }
        };
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Extend the unsupported DocEnvImpl type.

FREQUENCY : always



Comments
The standard doclet effectively requires that it should be given the DocletEnvironment given from the tool. You cannot provide a custom subtype. This restriction is specific to the standard doclet (and any subtypes that a user tries to create)
02-03-2023

There are two aspects to this one. 1. Why is a doclet trying to provide a custom DocletEnvironment, which is supposed to be a utility class providing access to info in the tool itself? And, do we want to support this usage? The submitter suggests this is useful to "customize" javadoc output, but this is not a recognized way to perform cusomization. 2. Why is WorkArounds casting DocletEnvironment down to DocEnvImpl? That appears to be to get at the underlying ToolEnv, which raises the underlying question of why does the doclet need to get at the toolEnv. Some of the usages can be replaced with better constructs (e.g. repeated use of toolEnv.getTypes()) but not all.
10-12-2019

This issue is reproducible on jdk13 ea b20 also == -sh-4.1$ /scratch/fairoz/JAVA/jdk13/jdk-13-ea+20/bin/javadoc -doclet bug.demo.NewDoclet -docletpath . bug.demo Loading source files for package bug.demo... Constructing Javadoc information... javadoc: error - fatal error encountered: java.lang.ClassCastException: class bug.demo.NewDoclet$1 cannot be cast to class jdk.javadoc.internal.tool.DocEnvImpl (bug.demo.NewDoclet$1 is in unnamed module of loader java.net.URLClassLoader @4ccabbaa; jdk.javadoc.internal.tool.DocEnvImpl is in module jdk.javadoc of loader 'app') javadoc: error - 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. java.lang.ClassCastException: class bug.demo.NewDoclet$1 cannot be cast to class jdk.javadoc.internal.tool.DocEnvImpl (bug.demo.NewDoclet$1 is in unnamed module of loader java.net.URLClassLoader @4ccabbaa; jdk.javadoc.internal.tool.DocEnvImpl is in module jdk.javadoc of loader 'app') at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.WorkArounds.<init>(WorkArounds.java:102) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.BaseConfiguration.initConfiguration(BaseConfiguration.java:402) at jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration.initConfiguration(HtmlConfiguration.java:767) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.AbstractDoclet.run(AbstractDoclet.java:104) at jdk.javadoc/jdk.javadoc.doclet.StandardDoclet.run(StandardDoclet.java:72) at bug.demo.NewDoclet.run(NewDoclet.java:22) at jdk.javadoc/jdk.javadoc.internal.tool.Start.parseAndExecute(Start.java:555) at jdk.javadoc/jdk.javadoc.internal.tool.Start.begin(Start.java:399) at jdk.javadoc/jdk.javadoc.internal.tool.Start.begin(Start.java:345) at jdk.javadoc/jdk.javadoc.internal.tool.Main.execute(Main.java:63) at jdk.javadoc/jdk.javadoc.internal.tool.Main.main(Main.java:52) 2 errors
20-05-2019

Additional information from submitter == Additional Information: The exact error message can be gotten by running a JavaDoc build utilizing the custom Doclet implementation: javadoc -doclet bug.demo.NewDoclet -docletpath . bug.demo The stacktrace I'm seeing is: javadoc: error - fatal error encountered: java.lang.ClassCastException: class bug.demo.NewDoclet$1 cannot be cast to class jdk.javadoc.internal.tool.DocEnvImpl (bug.demo.NewDoclet$1 is in unnamed module of loader java.net.URLClassLoader @32d992b2; jdk.javadoc.internal.tool.DocEnvImpl is in module jdk.javadoc of loader 'app') javadoc: error - 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. java.lang.ClassCastException: class bug.demo.NewDoclet$1 cannot be cast to class jdk.javadoc.internal.tool.DocEnvImpl (bug.demo.NewDoclet$1 is in unnamed module of loader java.net.URLClassLoader @32d992b2; jdk.javadoc.internal.tool.DocEnvImpl is in module jdk.javadoc of loader 'app') at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.WorkArounds.<init>(WorkArounds.java:102) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.BaseConfiguration.initConfiguration(BaseConfiguration.java:404) at jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration.initConfiguration(HtmlConfiguration.java:866) at jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.AbstractDoclet.run(AbstractDoclet.java:104) at jdk.javadoc/jdk.javadoc.doclet.StandardDoclet.run(StandardDoclet.java:72) at bug.demo.NewDoclet.run(NewDoclet.java:22)
20-05-2019

Please let us know, if any additional steps required to reproduce this issue?
17-05-2019

Javadoc is generated properly, i don't see any issue. Verified with 11.0.2 and 13 ea b19. == $ /Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/bin/javadoc NewDoclet.java Loading source file NewDoclet.java... Constructing Javadoc information... Standard Doclet version 13-ea Building tree for all the packages and classes... Generating ./NewDoclet.html... Generating ./package-summary.html... Generating ./package-tree.html... Generating ./constant-values.html... Building index for all the packages and classes... Generating ./overview-tree.html... Generating ./deprecated-list.html... Generating ./index-all.html... Building index for all classes... Generating ./allclasses-index.html... Generating ./allpackages-index.html... Generating ./index.html... Generating ./help-doc.html...
17-05-2019