-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
1.4.0
-
generic
-
generic
Name: inR10064 Date: 07/19/2000
A rule in 13.1 for qualifying type of field reference was changed in JLS-2
compared with JLS-1 but corresponding example in 13.4.7 stays unchanged
and contradicts the rule. There are two similar examples of such class
change in 13.4.7 of JLS-2.
Explanation of the example in 13.4.7 ( see below ) says that adding field h
to class Super does not break binary compatibility with other classes in the
example despite of the fact that the new field h hides field h, which is
declared in the superclass Hyper with different type. But in accordance with
new edition of the rule an incompatible class change should be detected
while execution of the example.
13.1 "The Form of a Binary" reads :
The required properties are:
........
* Given a legal expression denoting a field access in a class C, referencing
a field named f declared in a (possibly distinct) class or interface D,
we define the qualifying type of the field reference as follows:
- If the expression is of the form Primary.f then the compile-time type
of Primary is the qualifying type of the reference.
.......
The reference to f must be compiled into a symbolic reference to the qualifying
type of the reference, plus the simple name of the field, f.
So the classfile for Test should contain the reference "Super.h:Ljava/lang/String;"
while the recompiled class Super declares now the field "h:I" of different type.
This difference will lead to error while execution of the example.
Note that javac vv. 1.2.2, 1.3fcs-C, 1.4.0beta-b23 generate Test.class with
reference "Hyper.h:Ljava/lang/String;" which was demanded by JLS 1st ed.
--------------------------------------=== Example
In particular, no linkage error will occur in the case where a class could no
longer be recompiled because a field access previously referenced a field of
a superclass with an incompatible type. The previously compiled class with
such a reference will continue to reference the field declared in a superclass.
Thus compiling and executing the code:
class Hyper { String h = "hyper"; }
class Super extends Hyper { String s = "super"; }
class Test {
public static void main(String[] args) {
System.out.println(new Super().h);
}
}
produces the output:
hyper
Changing Super to be defined as:
class Super extends Hyper {
String s = "super";
int h = 0;
}
recompiling Hyper and Super, and executing the resulting new binaries with
the old binary of Test produces the output:
hyper
The field h of Hyper is output by the original binary of main.
--------------------------------------===
======================================================================