JDK-4274357 : Regression: bad classfile due to synthetic/explicit name clash
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 1999-09-22
  • Updated: 2001-03-29
  • Resolved: 2001-03-29
Related Reports
Duplicate :  
Description

Name: inc88864			Date: 09/22/99



Javac (build 1.3.0-G) does not prohibit use of names like 'val$argv' and 
'access$000'. Compiler uses such names for synthetic members, which it creates
to provide inner class semantics. Section "How do inner classes work?" of 
Inner Class Specification reads :

" It must be emphasized that these oddly-named "this$" and "val$" fields and 
extra constructor arguments are added by the compiler to the generated bytecodes, 
and cannot be directly referenced by Java source code.  "

After compiling of V.java (below) classfile V$1$Inn.class contains two fields 
'val$argv' of type "[Ljava/lang/String;", therefore ClassFormatError occurs 
while starting the V class (see trace below).

After compiling of A.java (below) classfile A.class contains two methods 
'access$000' of signature "(LA;)I". First of them is non-static so 
IncompatibleClassChangeError occurs while starting the A class (see trace below).

Note, that compiler does not allow use of name 'this$0', which also is name of synthetic
member, that compiler add to inner class.
 
Oldjavac and javacs in JDK 1.2.2, 1.2.1 compile the sources without errors.

--------------------------------------===  trace
% java V
Exception in thread "main" java.lang.ClassFormatError: V$1$Inn (Repeative field name/signature)
	at java.lang.ClassLoader.defineClass0(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:453)
......
% java A
Exception in thread "main" java.lang.IncompatibleClassChangeError
	at A$A2.x(A.java:5)
	at A.main(A.java:11)
%
--------------------------------------===  V.java
class V {
//    int this$0 = 15;
    interface I { 
	String s(); 
    }
    static I iv;

    public static void main( final String argv[] ) {
	class Inn implements I {
	    String val$argv[] = {"+45"};
	    public String s() {
		return argv[0] + val$argv[0];
	    }
	}
	iv = new Inn();
	System.out.println("iv.s() : " + iv.s());
    }
}
--------------------------------------===  A.java
class A {
    private int X=17;

    class A2 { 
	int x() { return X; }
    }

    int access$000(A a) { return 22; }

    public static void main( final String argv[] ) {
	System.out.println("X (==17) : " + new A().new A2().x() );
    }

}
--------------------------------------===

======================================================================

Comments
PUBLIC COMMENTS .
10-06-2004

EVALUATION See 4098167 for a discussion of the underlying specification issue. william.maddox@Eng 1999-09-22 In the specific case of synthetic fields, which are used only locally, the compiler can choose names that specifically avoid any names of similar syntactic form declared by the user. For example, a synthetic member val$foo$1 may be used to store an uplevel-referenced local variable when the user has explicitly declared a field named val$foo and thus preempted our first choice of name for the synthetic member. The innerclasses spec doesn't specifically indicate that this should be done, but I see no harm in it. Apparently, the pre-1.3 compiler *does* in fact do this, and javac 1.3 should do so as well. We rely on the fact that synthetic fields are private. Otherwise, we might be unable to declare a conflicting field in a subclass, thereby exposing the presence of the synthetic member in the user-visible namespace. A comprehesive fix would also deal with 4094180 as well. This bug addresses an aspect of the problem that was correctly handled in jdk1.2, but is not the entire story. william.maddox@Eng 2000-01-07 It would be most consistent to also rule out val$ for user programs. But best of all would be to get some new letter in the VM's alphabet for identifiers that is not allowed in Java source. neal.gafter@Eng 2001-01-04
04-01-2001