JDK-8075520 : Varargs access check mishandles capture variables
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 9
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2015-03-19
  • Updated: 2015-09-29
  • Resolved: 2015-04-16
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 8 JDK 9
8u60Fixed 9 b61Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
Consider this source code:
---
public class Test {

    private static <T> void test(Class<? extends T> clazz, T...
instances) {}

    public static void main(String[] args) {
        Object obj = null;
        test(obj.getClass());
    }

}
---

Compiling this on:
$ javac -fullversion
javac full version "1.9.0-ea-b54"

Leads to:
---
$ javac -source 6 -bootclasspath <path-to-JDK6-rt.jar> Test.java 
warning: [options] source value 1.6 is obsolete and will be removed in a future release
warning: [options] To suppress warnings about obsolete options, use -Xlint:-options.
Test.java:7: error: method test in class Test cannot be applied to given types;
        Test.test(obj.getClass());
            ^
  required: Class<? extends T>,T[]
  found: Class<CAP#1>
  reason: formal varargs element type CAP#1 is not accessible from class Test
  where T is a type-variable:
    T extends Object declared in method <T>test(Class<? extends T>,T...)
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ? extends Object
1 error
2 warnings
---

Workaround is to specify the method's parameter explicitly:
        Test.<Object>test(obj.getClass());

This may be caused by the fix for:

It seems it is caused by the fix for:
https://bugs.openjdk.java.net/browse/JDK-8039214
http://hg.openjdk.java.net/jdk9/dev/langtools/rev/414b82835861

Comments
Bug JDK-8077786 explains the discrepancy between -source 7 and -source 8. Under -source 8, the wrong type is being tested.
14-04-2015

I confirmed that a simple case of inaccessible varargs (no inference) fails as expected under jdk9 -source 9. So the fact that the error does not occur in these test cases probably has something to do with inference.
19-03-2015

An expanded test: <T> void varargs1(Iterable<? extends T> i, T... ts) {} <T> void varargs2(Iterable<T> i, T... ts) {} void test(Iterable<? extends String> arg) { varargs1(arg); varargs2(arg); } Observed behavior of the current jdk9 compiler: - Source 9: no errors - Source 8: no errors - Source 7: varargs1 and varargs2 errors - Source 6: varargs1 and varargs2 errors Observed behavior of javac 8 (u0 and u20): - Source 8: varargs2 error - Source 7: varargs2 error - Source 6: varargs2 error Observed behavior of javac 7 (u51): - Source 7: no errors - Source 6: no errors Notes: - The varargs access check was specified in 7; it's not clear whether this should have been guarded by -source 7+ or not (probably not, since without the check, runtime behavior is broken) - javac seems to be overlooking the erasure step in the specified check (JLS 15.12.3: "the type which is the erasure of Fn") - JDK-8039214 exposes the bug in some new places (varargs1), but it existed beforehand (varargs2) - It's not clear to me why -source 8 (and 9) exhibits different behavior under jdk9 than jdk8
19-03-2015