JDK-6313164 : javac generates code that fails byte code verification for the varargs feature
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2005-08-18
  • Updated: 2017-05-16
  • 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 7
7 b130Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_03-b07)
Java HotSpot(TM) Server VM (build 1.5.0_03-b07, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux  2.4.9-e.25kmap1enterprise #1 SMP

A DESCRIPTION OF THE PROBLEM :
suppose class A is package private, class B is  public and in
the same package as A and extends A, a public method on B
has the signature of foo(A... args).

class C is in a different package, and has an invocation of
 foo(new B(), new B())

class C will compile, but the resulting byte code does not run
(gets an java.lang.IllegalAccessError), since javac would
generate a  new A[] call for class C for the varargs invocation.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile the source code included below,
 run it as follows:

java -Xfuture -classpath [classpath pointing to the classfiles] p2.C

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
should fail to compile since p2.C doesn't have access to
p1.A
ACTUAL -
compiler generated no error, but when java is invoked on
the resulting class file (with the -Xfuture option, or if classes
in p2 and p1 are loaded from different file system pathes),
you get a runtime error:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class p1.A from class p2.C
        at p2.C.main(C.java:6)

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.IllegalAccessError: tried to access class p1.A from class p2.C
        at p2.C.main(C.java:6)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
A.java
----------
package p1;

class A {
  A() {
  }
}
------------

B.java
------------
package p1;
import java.io.*;
public class B extends A {
 public B() {}

 public void foo(A... args) {
  System.out.println(args);
 }
}
-----------

C.java
----------
package p2;
import p1.B;
public class C {

 public static final void main(String[] args) {
   (new B()).foo(new B(), new B());
 }
}
---------


---------- END SOURCE ----------

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

EVALUATION As written, the specification supports the implemented behavior. It would seem reasonable to expect a compile-time error if the type of a var-arg formal parameter were inaccessible. One might debate if, in such a circumstance, the method should even be considered applicable. However, the only sane path is to consider the call equivalent to its translation, not only at run time (which it already is), but at compile time. This may lead to difficulties with generic methods. It is therefore necessary to specify he check explicitly. In JLS 15.12.4.3, one would add the check: If all of the following conditions hold a. The compile-time declaration of the method invocation is a variable arity method m. b. The inferred type of the final formal parameter of m for this invocation is T[]. c. m is invoked with actual argument expressions (e1 ... en-1, en, ..., ek) d. m is being invoked with k != n actual argument expressions, or, m is being invoked with k = n actual argument expressions and the type of the kth argument expressions is not assignment compatible with T[] then it is a compile time error if the erasure of T is not accessible at the point of invocation.
23-08-2005

EVALUATION The specification says that the expression foo(new B(), new B()) should be evaluated at runtime as if it was written: foo(new p1.A[] {new B(), new B()}) However, the specification doesn't clearly say whether or not it is a compile time error. I'm reassigning this to specification to clarify. Please reassign to compiler when resolved.
23-08-2005