JDK-6665223 : Static import of inherited protected method causes compiler exception
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2008-02-20
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
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 Other
6u10Fixed 7 b29Fixed OpenJDK6Fixed
1.6.0_10-ea (under Linux)
1.6.0_03-p3 (under Mac OS X)

I hit this bug on the SoyLatte port of JDK 6 to Mac OS, but the maintainer of that package reproduced it under Linux too.

Compiling the given file which contains a particular static import causes a compiler exception.

Compile the given files

Should compile it
Causes a compiler exception

Information:An exception has occurred in the compiler (1.6.0_03-p3). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
Information:	at com.sun.tools.javac.code.Symbol.packge(Symbol.java:274)
Information:	at com.sun.tools.javac.code.Symbol.isInheritedIn(Symbol.java:344)
Information:	at com.sun.tools.javac.comp.Resolve.selectBest(Resolve.java:539)
Information:	at com.sun.tools.javac.comp.Resolve.findFun(Resolve.java:808)
Information:	at com.sun.tools.javac.comp.Resolve.resolveMethod(Resolve.java:1179)
Information:	at com.sun.tools.javac.comp.Attr.visitIdent(Attr.java:1706)
Information:	at com.sun.tools.javac.tree.JCTree$JCIdent.accept(JCTree.java:1547)
Information:	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:360)
Information:	at com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:377)
Information:	at com.sun.tools.javac.comp.Attr.visitApply(Attr.java:1241)
Information:	at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1210)
Information:	at com.sun.tools.javac.comp.Attr.attribArgs(Attr.java:421)
Information:	at com.sun.tools.javac.comp.Attr.visitApply(Attr.java:1233)
Information:	at com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:384)
Information:	at com.sun.tools.javac.comp.Attr.visitExec(Attr.java:1017)
Information:	at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1074)
Information:	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:397)
Information:	at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:413)
Information:	at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:715)
Information:	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:739)
Information:	at com.sun.tools.javac.comp.Attr.visitMethodDef(Attr.java:634)
Information:	at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:639)
Information:	at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:2688)
Information:	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:2619)
Information:	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:2555)
Information:	at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1036)
Information:	at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:765)
Information:	at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:730)
Information:	at com.sun.tools.javac.main.Main.compile(Main.java:353)
Information:	at com.sun.tools.javac.main.Main.compile(Main.java:279)
Information:	at com.sun.tools.javac.main.Main.compile(Main.java:270)
Information:	at com.sun.tools.javac.Main.compile(Main.java:69)
Information:	at com.sun.tools.javac.Main.main(Main.java:54)
Information:	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Information:	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
Information:	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
Information:	at java.lang.reflect.Method.invoke(Method.java:597)
Information:	at com.intellij.rt.compiler.JavacRunner.main(JavacRunner.java:53)
Information:Compilation completed with 1 error and 0 warnings
Information:1 error
Information:0 warnings
Error:Compiler internal error. Process terminated with exit code 4

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package pkg;

import static pkg.BasicallyEmptyClass.sayHello;

public class ClassThatWontCompile {
    public void tryToPrint() {
package pkg;

public final class BasicallyEmptyClass extends AbstractClassWithStatic {}

abstract class AbstractClassWithStatic {

	protected static String sayHello(Object objectToIgnore){
        return "hello";

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

Replace the static import with a fully qualified reference to the static method.

Release Regression From : 5.0u12
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Release Regression From : 5.0u12
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

SUGGESTED FIX a webrev of the fix is available at: http://sa.sfbay.sun.com/projects/langtools_data/7/6665223/

EVALUATION This CR shows a problem in Resolve.isAccessible() method. Accessibility rules for protected members doesn't take into consideration static members. Current javac rules impose that a protected member C.x, in order to be accessible from T the following conditions must hold: 1) C is in the same package of T, or C is inherited by T 2) No members in T overrides C.x The implementation of 2) is a bit tricky and relies upon the Symbol.implementation() method: this how the rule looks like in javac: 2b) the implementation of C.x in T is C.x itself (which means that T is inheriting C.x wihout overriding it) This trick works most of the times, but it relies on the internals of the implementation of the Symbol.implementation() method; in our case, since T.x is a static member, in principle there would be no no need of checking for overriding (that cannot take place!). Moreover, when Resolve.isAccessible() is called from the code in either Resolve.findFun() or Resolve.findVar(), strange things might happen if the static method/field to be resolved comes from a static import. Static imports somehow need some special handling: when a field/method m is found in the static scope of a the type C (that has been statically imported), two situation may arise: 1) m is indeed a member of C - then resolution takes place as always, and no bug occurs; this process is similar to resolving a static method/field given the fully qualified type-expression C.m 2) m is in the static scope of C, but it has not been defined in some other type B from which C inherithed it. In this case javac replaces the owner of m's symbol to be C, so that B.m becomes C.m. But what does it mean? If B.m were a method, C.m compiler generated symbol would correspond to C's overriden version of B.m. But this means that when checking for accessibility we have that condition 2 for accessibilit ydoes not hold anymore, since: - No members in T overrides C.x -- it's not true (C.x seems to override B.x). The solution to this problem, has anticipated, is to avoid the overriding check when checking for accessibility of static protected methods, as static methods cannot be overriden. This check generates only confusion and badly copes with features likes static imports.