JDK-6397652 : REGRESSION: javac compilation failure when imported class with $ sign in the name
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-03-13
  • Updated: 2012-03-23
  • Resolved: 2006-05-13
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
6 b85Fixed
Related Reports
Relates :  
Relates :  
Description
Since jdk6.0-b75 javac fails to compile a source which contains
an import of the class with dollar sign in the name.
Please see minimized test below to reproduce this failure.

Minimized test:
===============
--- com/test/Test.java ---
package com.test;

public class Test {

    public Test() {
    }

}
---com/test/Test.java---

--- com/test/Test$Test.java ---
package com.test;

public class Test$Test {

    public Test$Test(double value) {
    }

}
--- com/test/Test$Test.java ---

--- T1.java ---
import com.test.Test$Test;

public class T1 {

    public static void main(String[] args) {
        Object obj = new Test$Test(1.0);
    }
}
---end-of- ---

Minimized test output:
=====================
<yg153347@oink> /java/re/jdk/6.0/promoted/beta2/b75/binaries/solaris-sparc/bin/javac com/test/*.java
<yg153347@oink> /java/re/jdk/6.0/promoted/beta2/b75/binaries/solaris-sparc/bin/javac T1.java
T1.java:1: com.test.Test$Test is not public in com.test.Test; cannot be accessed from outside package
import com.test.Test$Test;
               ^
T1.java:6: cannot find symbol
symbol  : constructor Test$Test(double)
location: class Test$Test
        Object obj = new Test$Test(1.0);
                     ^
2 errors
=====================

There is no errors if I compile all files together:
<yg153347@oink> /java/re/jdk/6.0/promoted/beta2/b75/binaries/solaris-sparc/bin/javac com/test/*.java T1.java
  or use previous Mustang builds (b74):
<yg153347@oink> /java/re/jdk/6.0/promoted/beta2/b74/binaries/solaris-sparc/bin/javac com/test/*.java
<yg153347@oink> /java/re/jdk/6.0/promoted/beta2/b74/binaries/solaris-sparc/bin/javac T1.java
  or Tiger's javac:
<yg153347@oink> /java/re/jdk/1.5.0/archive/fcs/binaries/solaris-sparc/bin/javac com/test/*.java
<yg153347@oink> /java/re/jdk/1.5.0/archive/fcs/binaries/solaris-sparc/bin/javac T1.java

Comments
SUGGESTED FIX Webrev of changes: http://sa.sfbay/projects/langtools/bugid_summary.pl?bugid=6397652
06-05-2006

EVALUATION The problem was that ClassReader.completeEnclosing(ClassSymbol) creating non-existing using ClassReader.enterClass(Name, TypeSymbol). It is better to search the package scope for an existing symbol.
02-05-2006

SUGGESTED FIX --- /home/ahe/ws/6397652-dollar_crash.ws/6397652/webrev/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java- 2006-05-01 20:54:13.291674538 -0700 +++ /home/ahe/ws/6397652-dollar_crash.ws/6397652/webrev/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java+ 2006-05-01 20:54:13.315671182 -0700 @@ -1714,23 +1714,22 @@ private void completeOwners(Symbol o) { if (o.kind != PCK) completeOwners(o.owner); o.complete(); } + /** + * Tries to complete lexically enclosing classes if c looks like a + * nested class. This is similar to completeOwners but handles + * the situation when a nested class is accessed directly as it is + * possible with the Tree API or javax.lang.model.*. + */ private void completeEnclosing(ClassSymbol c) { if (c.owner.kind == PCK) { - PackageSymbol owner = (PackageSymbol)c.owner; - String name = c.name.toString(); - int index = name.lastIndexOf("$"); - if (index > -1) { - Symbol encl = enterClass(names.fromString(name.substring(0, index)), owner); - try { + for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) { + Symbol encl = c.owner.members().lookup(name).sym; + if (encl != null) encl.complete(); - c.owner = encl; - } catch (CompletionFailure ex) { - owner.members().remove(encl); - } } } } /** We can only read a single class file at a time; this --- /home/ahe/ws/6397652-dollar_crash.ws/6397652/webrev/src/share/classes/com/sun/tools/javac/util/Convert.java- 2006-05-01 20:54:15.796324273 -0700 +++ /home/ahe/ws/6397652-dollar_crash.ws/6397652/webrev/src/share/classes/com/sun/tools/javac/util/Convert.java+ 2006-05-01 20:54:15.802323434 -0700 @@ -291,9 +291,16 @@ public static String packagePart(String classname) { int lastDot = classname.lastIndexOf('.'); return (lastDot < 0 ? "" : classname.substring(0, lastDot)); } -} - - + public static List<Name> enclosingCandidates(Name name) { + List<Name> names = List.nil(); + int index; + while ((index = name.lastIndexOf((byte)'$')) > 0) { + name = name.subName(0, index); + names = names.prepend(name); + } + return names; + } +}
02-05-2006

EVALUATION This is probably a consequence of 6374357. This is probably a minor issue in ClassReader.completeEnclosing(ClassSymbol) which fails to detect that com.test.Test is *not* an owner of com.test.Test$Test.
13-03-2006