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

Inconsistent Execution for Protected Method Access in Inherited Class

XMLWordPrintable

    • x86_64
    • windows

      ADDITIONAL SYSTEM INFORMATION :
      ADDITIONAL SYSTEM INFORMATION :

      ```
      OS:
      Operating System Name: Windows 11
      Operating System Architecture: amd64
      Operating System Version: 10.0

      ```

      OpenJDK version:

      ```
      java version "1.8.0_441"
      Java(TM) SE Runtime Environment (build 1.8.0_441-b07)
      Java HotSpot(TM) 64-Bit Server VM (build 25.441-b07, mixed mode)

      java version "11.0.26" 2025-01-21 LTS
      Java(TM) SE Runtime Environment 18.9 (build 11.0.26+7-LTS-187)
      Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.26+7-LTS-187, mixed mode)

      openjdk version "1.8.0_452"
      IBM Semeru Runtime Open Edition (build 1.8.0_452-b09)
      Eclipse OpenJ9 VM (build openj9-0.51.0, JRE 1.8.0 Windows 11 amd64-64-Bit Compressed References 20250504_1243 (JIT enabled, AOT enabled)
      OpenJ9 - 31cf5538b0
      OMR - 9bcff94a2
      JCL - a00de86921 based on jdk8u452-b09)

      openjdk version "11.0.27" 2025-04-15
      IBM Semeru Runtime Open Edition 11.0.27.0 (build 11.0.27+6)
      Eclipse OpenJ9 VM 11.0.27.0 (build openj9-0.51.0, JRE 11 Windows 11 amd64-64-Bit Compressed References 20250504_1192 (JIT enabled, AOT enabled)
      OpenJ9 - 31cf5538b0
      OMR - 9bcff94a2
      JCL - 3e17c0897e based on jdk-11.0.27+6)

      ```
      Output from `java -version`.

      A DESCRIPTION OF THE PROBLEM :
      Given a test case, we found that the execution results of this test case on different JVMs are different, the simplified test case can be found below. In summary, Hotspot threw VerifyError, while the J9 ran normally.

      REGRESSION : Last worked in version 8

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      The following code can be used to generate the test cases(.class file) that reproduces the above process:

      ```java
      import java.io.File;
      import java.io.FileOutputStream;
      import java.io.IOException;

      public class BytecodeUtil {
          public static void main(String args[]) {
              // create package
              String baseDir = "./your_dir"; // your base dir

              File P0 = new File(baseDir + "/" + "P0");
              File P1 = new File(baseDir + "/" + "P1");
              P0.mkdirs();
              P1.mkdirs();

              String P0_C2_bytecodeInStr = "CAFEBABE00000034002D01000550302F433207000101000550312F43310700030100063C696E69743E0100032829560C000500060A000400070100047465737401001528294C6A6176612F6C616E672F496E74656765723B01000950312F48656C70657207000B010005676574433101000928294C50312F43313B0C000D000E0A000C000F01000550312F43300700110100016D0C0013000A0A001200140100046D61696E010016285B4C6A6176612F6C616E672F537472696E673B29560C0009000A0A000200180100106A6176612F6C616E672F53797374656D07001A0100036F75740100154C6A6176612F696F2F5072696E7453747265616D3B0C001C001D09001B001E01000E52657475726E2076616C75653A200800200100136A6176612F696F2F5072696E7453747265616D0700220100057072696E74010015284C6A6176612F6C616E672F537472696E673B29560C002400250A002300260100077072696E746C6E010015284C6A6176612F6C616E672F4F626A6563743B29560C002800290A0023002A010004436F64650021000200040000000000030001000500060001002C0000001100010001000000052AB70008B10000000000090009000A0001002C000000150001000100000009B800104B2AB60015B0000000000009001600170001002C0000001E0003000200000012B800194CB2001F591221B600272BB6002BB1000000000000" ;
              String P0_helper_bytecodeInStr = "CAFEBABE00000034000F01000950302F48656C7065720700010100106A6176612F6C616E672F4F626A6563740700030100063C696E69743E0100032829560C000500060A00040007010005676574433201000928294C50302F43323B01000550302F433207000B0A000C0007010004436F64650021000200040000000000020001000500060001000E0000001100010001000000052AB70008B10000000000090009000A0001000E00000016000200010000000ABB000C59B7000D4B2AB0000000000000" ;
              String P1_C0_bytecodeInStr = "CAFEBABE00000034001201000550312F43300700010100106A6176612F6C616E672F4F626A6563740700030100063C696E69743E0100032829560C000500060A000400070100016D01001528294C6A6176612F6C616E672F496E74656765723B0100116A6176612F6C616E672F496E746567657207000B0300000000010004284929560C0005000E0A000C000F010004436F6465002100020004000000000002000100050006000100110000001100010001000000052AB70008B10000000000040009000A0001001100000016000300010000000ABB000C59120DB70010B0000000000000" ;
              String P1_C1_bytecodeInStr = "CAFEBABE00000034000A01000550312F433107000101000550312F43300700030100063C696E69743E0100032829560C000500060A00040007010004436F6465002100020004000000000001000100050006000100090000001100010001000000052AB70008B1000000000000" ;
              String P1_Helper_bytecodeInStr = "CAFEBABE00000034001401000950312F48656C7065720700010100106A6176612F6C616E672F4F626A6563740700030100063C696E69743E0100032829560C000500060A00040007010005676574433001000928294C50312F43303B01000550312F433007000B0A000C0007010005676574433101000928294C50312F43313B01000550312F43310700100A00110007010004436F6465002100020004000000000003000100050006000100130000001100010001000000052AB70008B10000000000090009000A0001001300000016000200010000000ABB000C59B7000D4B2AB0000000000009000E000F0001001300000016000200010000000ABB001159B700124B2AB0000000000000" ;

              try (FileOutputStream fos = new FileOutputStream(P0.getAbsolutePath() + "/" + "C2.class")) {
                  byte[] P0_C2_bytecode = hexStringToByteArray(P0_C2_bytecodeInStr);
                  fos.write(P0_C2_bytecode);
              } catch (IOException e) {
                  e.printStackTrace();
              }

              try (FileOutputStream fos = new FileOutputStream(P0.getAbsolutePath() + "/" + "Helper.class")) {
                  byte[] P0_helper_bytecode = hexStringToByteArray(P0_helper_bytecodeInStr);
                  fos.write(P0_helper_bytecode);
              } catch (IOException e) {
                  e.printStackTrace();
              }

              try (FileOutputStream fos = new FileOutputStream(P1.getAbsolutePath() + "/" + "C0.class")) {
                  byte[] P1_C0_bytecode = hexStringToByteArray(P1_C0_bytecodeInStr);
                  fos.write(P1_C0_bytecode);
              } catch (IOException e) {
                  e.printStackTrace();
              }

              try (FileOutputStream fos = new FileOutputStream(P1.getAbsolutePath() + "/" + "C1.class")) {
                  byte[] P1_C1_bytecode = hexStringToByteArray(P1_C1_bytecodeInStr);
                  fos.write(P1_C1_bytecode);
              } catch (IOException e) {
                  e.printStackTrace();
              }

              try (FileOutputStream fos = new FileOutputStream(P1.getAbsolutePath() + "/" + "Helper.class")) {
                  byte[] P1_Helper_bytecode = hexStringToByteArray(P1_Helper_bytecodeInStr);
                  fos.write(P1_Helper_bytecode);
              } catch (IOException e) {
                  e.printStackTrace();
              }

          }

          public static byte[] hexStringToByteArray(String hexString) {
              int length = hexString.length();
              byte[] byteArray = new byte[length / 2];
              for (int i = 0; i < length; i += 2) {
                  int byteValue = Integer.parseInt(hexString.substring(i, i + 2), 16);
                  byteArray[i / 2] = (byte) byteValue;
              }
              return byteArray;
          }
      }

      ```

      Note: modify the paths according to your needs.

      Repoduce:
      ```
      >>> path_to_jdk/Hotspot_1.8.0_441/bin/java -cp . P0.C2

      >>> path_to_jdk/Hotspot_11.0.26/bin/java -cp . P0.C2

      >>> path_to_jdk/openj9/1.8.0_452/bin/java -cp . P0.C2

      >>> path_to_jdk/openj9/11.0.27/bin/java -cp . P0.C2
      ```

      ACTUAL -
      The output is as follows:

      J9(1.8.0_452):
      ```
      Return value: 0
      ```

      J9(11.0.27):
      ```
      Return value: 0
      ```

      Hotspot(1.8.0_441):
      ```
      Exception in thread "main" java.lang.VerifyError: Bad access to protected data in invokevirtual
      Exception Details:
        Location:
          P0/C2.test()Ljava/lang/Integer; @5: invokevirtual
        Reason:
          Type 'P1/C1' (current frame, stack[0]) is not assignable to 'P0/C2'
        Current Frame:
          bci: @5
          flags: { }
          locals: { 'P1/C1' }
          stack: { 'P1/C1' }
        Bytecode:
          0x0000000: b800 104b 2ab6 0015 b0

              at java.lang.Class.getDeclaredMethods0(Native Method)
              at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
              at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
              at java.lang.Class.getMethod0(Class.java:3018)
              at java.lang.Class.getMethod(Class.java:1784)
              at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:690)
              at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:672)
      ```

      Hotspot(11.0.26):

      ```
      Error: Unable to initialize main class P0.C2
      Caused by: java.lang.VerifyError: Bad access to protected data in invokevirtual
      Exception Details:
        Location:
          P0/C2.test()Ljava/lang/Integer; @5: invokevirtual
        Reason:
          Type 'P1/C1' (current frame, stack[0]) is not assignable to 'P0/C2'
        Current Frame:
          bci: @5
          flags: { }
          locals: { 'P1/C1' }
          stack: { 'P1/C1' }
        Bytecode:
          0000000: b800 104b 2ab6 0015 b0
      ```

      ---------- BEGIN SOURCE ----------
      ```java
      package P0;

      import P1.C0;
      import P1.C1;
      import P1.Helper;
      import java.io.PrintStream;

      public class C2 extends C1 {
          public C2() {
          }

          public static Integer test() {
              C1 var0 = Helper.getC1();
              return ((C0)var0).m();
          }

          public static void main(String[] var0) {
              Integer var1 = test();
              PrintStream var10000 = System.out;
              var10000.print("Return value: ");
              var10000.println(var1);
          }
      }
      ```

      ```java
      package P1;

      public class C1 extends C0 {
          public C1() {
          }
      }
      ```

      ```java
      package P1;

      public class C0 {
          public C0() {
          }

          protected Integer m() {
              return new Integer(0);
          }
      }
      ```

      ```java
      package P1;

      public class Helper {
          public Helper() {
          }

          public static C0 getC0() {
              C0 var0 = new C0();
              return var0;
          }

          public static C1 getC1() {
              C1 var0 = new C1();
              return var0;
          }
      }
      ```

      ```java
      package P0;

      public class Helper {
          public Helper() {
          }

          public static C2 getC2() {
              C2 var0 = new C2();
              return var0;
          }
      }
      ```
      ---------- END SOURCE ----------

            dholmes David Holmes
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: