JDK-6468404 : ExecutableElement.getParameters() uses raw type for class loaded from -g bytecode
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 2.0,6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux,solaris_9
  • CPU: x86,sparc
  • Submitted: 2006-09-07
  • Updated: 2011-03-08
  • Resolved: 2011-03-08
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.
JDK 6 JDK 7
6u1Fixed 7 b03Fixed
Related Reports
Duplicate :  
Duplicate :  
Description
Create and compile a test class with JDK 6:

---%<---
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ExecutableType;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
public class Test {
    public static void main(String[] args) throws Exception {
        String dest = System.getProperty("java.io.tmpdir");
        class DummyFO extends SimpleJavaFileObject {
            String n;
            public DummyFO(String n) {
                super(URI.create("nowhere:/" + n + ".java"), JavaFileObject.Kind.SOURCE);
                this.n = n;
            }
            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
                return "public class " + n + " {" + n + "(java.util.List<String> l) {}}";
            }
        }
        System.out.println("Compiling with sources:");
        JavaCompiler.CompilationTask task = ToolProvider.getSystemJavaCompiler().getTask(
                null, null, null,
                Arrays.asList("-d", dest),
                null, Collections.singleton(new DummyFO("C")));
        task.setProcessors(Collections.singleton(new P()));
        task.call();
        System.out.println("Compiling with binaries w/o -g:");
        task = ToolProvider.getSystemJavaCompiler().getTask(
                null, null, null,
                Arrays.asList("-classpath", dest, "-d", dest),
                null, Collections.singleton(new DummyFO("Dummy")));
        task.setProcessors(Collections.singleton(new P()));
        task.call();
        task = ToolProvider.getSystemJavaCompiler().getTask(
                null, null, null,
                Arrays.asList("-d", dest, "-g"),
                null, Collections.singleton(new DummyFO("C")));
        task.call();
        System.out.println("Compiling with binaries w/ -g:");
        task = ToolProvider.getSystemJavaCompiler().getTask(
                null, null, null,
                Arrays.asList("-classpath", dest, "-d", dest),
                null, Collections.singleton(new DummyFO("Dummy")));
        task.setProcessors(Collections.singleton(new P()));
        task.call();
    }
    @SupportedAnnotationTypes("*")
    @SupportedSourceVersion(SourceVersion.RELEASE_6)
    static class P extends AbstractProcessor {
        boolean ran = false;
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            if (!ran) {
                ran = true;
                ExecutableElement m = (ExecutableElement) processingEnv.getElementUtils().getTypeElement("C").getEnclosedElements().get(0);
                System.out.println("method: " + m);
                System.out.println("parameters[0]: " + m.getParameters().get(0).asType());
                System.out.println("parameterTypes[0]: " + ((ExecutableType) m.asType()).getParameterTypes().get(0));
            }
            return true;
        }
    }
}
---%<---

Expected output:

---%<---
Compiling with sources:
method: C(java.util.List<java.lang.String>)
parameters[0]: java.util.List<java.lang.String>
parameterTypes[0]: java.util.List<java.lang.String>
Compiling with binaries w/o -g:
method: C(java.util.List<java.lang.String>)
parameters[0]: java.util.List<java.lang.String>
parameterTypes[0]: java.util.List<java.lang.String>
Compiling with binaries w/ -g:
method: C(java.util.List<java.lang.String>)
parameters[0]: java.util.List<java.lang.String>
parameterTypes[0]: java.util.List<java.lang.String>
---%<---

Actual output w/ -showversion:

---%<---
java version "1.6.0-rc"
Java(TM) SE Runtime Environment (build 1.6.0-rc-b98)
Java HotSpot(TM) Client VM (build 1.6.0-rc-b98, mixed mode, sharing)

Compiling with sources:
method: C(java.util.List<java.lang.String>)
parameters[0]: java.util.List<java.lang.String>
parameterTypes[0]: java.util.List<java.lang.String>
Compiling with binaries w/o -g:
method: C(java.util.List<java.lang.String>)
parameters[0]: java.util.List<java.lang.String>
parameterTypes[0]: java.util.List<java.lang.String>
Compiling with binaries w/ -g:
method: C(java.util.List<java.lang.String>)
parameters[0]: java.util.List
parameterTypes[0]: java.util.List<java.lang.String>
---%<---

When loading the class from bytecode compiled with -g, the ExecutableElement for <init>(List<String>) reports parameters[0].asType() as being List, whereas it should be List<String>. ExecutableType gets it right.

But the bug does not occur if you create the parse tree from sources; or if you create it from classes compiled without -g.

Comments
SUGGESTED FIX Webrev of changes: http://sa.sfbay/projects/langtools/bugid_summary.pl?bugid=6468404 See also attachment 6468404.tar.gz.
20-10-2006

EVALUATION I also fixed a number of regression tests which had their golden files affected by 6379520.
17-10-2006

EVALUATION I rewrote the submitted test case to use StandardJavaFileManager.setLocation() and I noticed that the locations are reset during annotation processing and subsequent calls to getTask. The problem is that locations are stored in a com.sun.javac.util.Paths instance which is discarded when a new context is supplied to DefaultFileManager. So I added a setContext method to Paths.
17-10-2006

EVALUATION Looks like a bug in the code for reading variable names in ClassReader.
08-09-2006

WORK AROUND Always use ExecutableType.getParameterTypes(), not ExecutableElement.getParameters(), if you need to know exact types of method/constructor params for classes which might be in the classpath rather than the compilation unit.
07-09-2006