Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4683294

Inner class calls wrong version of inherited protected method

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 1.4.0
    • tools
    • x86
    • linux



      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)
      ======================================================================

            gafter Neal Gafter (Inactive)
            nthompsosunw Nathanael Thompson (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: