Name: nt126004 Date: 05/10/2002
FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
It happens with -source 1.4 and -source 1.3. It also happens using the
jdk1.3.1 compiler. It even happens using version 1.12 of Jikes.
FULL OPERATING SYSTEM VERSION :
glibc-2.1.3-22.1
Linux scratchy.west.quiq.com 2.2.20 #2 Fri Mar 22
09:54:08 PST 2002 i686 unknown
Red Hat Linux release 6.2 (Piglet)
VA Linux Release 6.2.4 02/21/01
A DESCRIPTION OF THE PROBLEM :
I have an inner class that calls a protected method of
its containing class. This protected method is
inherited from the outer class's parent, which lives in
a different package, and is not overridden by the outer
class.
The surprising (and I believe incorrect) behavior is
that the inner class's invocation of this method
results in calling the parent class's implementation of
the method, even if a subclass of the outer class
overrides the method. In JVM terms, the synthetic
method generated to allow the inner class access to the
protected method has an "invokespecial" instruction
instead of an "invokevirtual".
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile the classes given below: javac -classpath .
pkg1/A.java pkg2/[BC].java
2. Run class C: java -cp . pkg2.C
3. If you'd like to look at the offending instruction in
the access method, take a look at the instructions: javap
-c -classpath . pkg2.B
EXPECTED VERSUS ACTUAL BEHAVIOR :
I expected C's version of the protected method to be
called from either B's inner class or directly from B.
Instead, when I call the method from the inner class,
A's version is called.
The output from executing the C class is as follows:
In B.runTest's Runnable's run method
In A.protectedMethod
In C.publicMethod
In B.runTest
In C.protectedMethod
In C.publicMethod
I expected the "In A.protectedMethod" to be "In
C.protectedMethod".
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
----File pkg1/A.java--------
package pkg1;
public class A
{
protected void protectedMethod() {
System.out.println( "In A.protectedMethod" );
}
public void publicMethod() {
System.out.println( "In A.publicMethod" );
}
}
----File pkg2/B.java--------
package pkg2;
public class B extends pkg1.A
{
public void runTest()
{
Runnable r = new Runnable() {
public void run() {
System.out.println( "In B.runTest's Runnable's run method"
);
protectedMethod();
publicMethod();
}
};
r.run();
System.out.println();
System.out.println( "In B.runTest" );
protectedMethod();
publicMethod();
}
}
----File pkg2/C.java--------
package pkg2;
public class C extends B
{
protected void protectedMethod() {
System.out.println( "In C.protectedMethod" );
}
public void publicMethod() {
System.out.println( "In C.publicMethod" );
}
public static void main( String[] args ) {
new C().runTest();
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Write your own access method.
(Review ID: 146229)
======================================================================
- duplicates
-
JDK-4406917 static call instead of virtual call in inner classes (access method bug)
-
- Closed
-