JDK-4098167 : Use of '$' by inner classes conflicts with uses permitted by JLS
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 1.2.0,1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic,windows_nt,windows_2000
  • CPU: generic,x86
  • Submitted: 1997-12-09
  • Updated: 2011-10-31
  • Resolved: 2011-10-31
Related Reports
Relates :  
Relates :  
Relates :  
Description
Two recent bug reports (4096303 and 4094180) have once again raised
issues concerning the use of '$' characters in Java identifiers.  The
JLS states that "The '$' character should be used only in mechanically
generated Java code or, rarely, to access pre-existing names on legacy
systems."  Thus, although discouraged in ordinary usage, the compiler
cannot rule out such names, and the reservation of certain names by the
inner class mechanism is indeed an incompatible change to the Java
language (as it existed prior to 1.1) that must be precisely defined.

The following program illustrates three of the ways in which a name
appearing in Java source can conflict with a name generated implicitly
by the compiler according to the inner classes specification:

	class C {
	  class N {
	    int this$0;		//BAD
	  }
	}
	class C$N { }		//BAD

	class Baz {
	  void quux() {
	     class Quem {}
	     }
	}
	class Baz$1$Quem {}	//BAD

It is not sufficient merely to advise users against using '$' in
identifiers, as we must offer guidance to those who are writing
automatic program generators for whom we have ostensibly reserved such
names.

william.maddox@Eng 1997-12-09


Name: skT45625			Date: 05/10/2000


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

Starting with JDK 1.3, javac breaks on "this$0" references. Try compiling the
following example:

public class TestInner {

    public class Inner {

	public void test() {
	    System.out.println("My outer class: "+this$0);
	}
    }

    public void test() {
	Inner inner = new Inner();
	inner.test();
    }

    static public void main(String[] args) {
	TestInner inner = new TestInner();
	inner.test();
    }
}

C:\Current\Server>javac *.java
TestInner.java:6: cannot resolve symbol
symbol  : variable this$0
location: class TestInner.Inner
            System.out.println("My outer class: "+this$0);
(Review ID: 104660)
======================================================================

Comments
EVALUATION JVMS7 relaxes the content of CONSTANT_NameAndType_info CP entries (w.r.t. JVMS2) from Java language identifiers to unqualified names (4.3.2). Therefore, CP entries which represent class names and field/method identifiers, as well as field/method definitions themselves, can use identifiers outside the Java language. JLS7 still warns against using '$' in identifiers, and does not specify a space of identifiers reserved for mechanical use. The overlap between synthetic names and user names is not a problem in practice.
24-04-2007

WORK AROUND Name: skT45625 Date: 05/10/2000 Moving the inner class out would avoid the use of this$0. Otherwise, go back to JDK 1.2. (Review ID: 104660) ======================================================================
13-09-2004

EVALUATION Agreed. gilad.bracha@eng 1997-12-11 The Tiger changes to the VM spec will likely add additional characters that are legal in VM identifiers that are not legal in Java identifiers. That would allow the compiler to avoid most of the conflicts. ###@###.### 2003-05-12
12-05-2003

SUGGESTED FIX Use another character for forming inner class names. This would raise compatibility issues, possibly requiring VM and verifier changes. Alternately, formally disallow '$' in Java identifiers, possibly admitting them for critical needs/backward compatibility with the proviso that implementation-dependent behavior may be observed. This would be a JLS change, and would also have compatibility implication. william.maddox@Eng 1997-12-09
09-12-1997