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

java.lang.Class.isPrimitive() (C1) returns wrong result if Klass* is aligned to 32bit

    Details

    • Subcomponent:
    • Introduced In Build:
      b112
    • Introduced In Version:
      9
    • Resolved In Build:
      b22
    • CPU:
      x86

      Description

      A Klass* allocated at a 32bit aligned address (all lower 32 bits set to zero) may cause jlClass::isPrimitive() to return the wrong value.

      The reason is that the C1 intrinsic for jlClass::isPrimitive(), which compares the Klass* address with NULL, does so using a 32bit compare:

      -------------

       6512 Compiled method (c1) 822 31 1 java.lang.invoke.MethodTypeForm::canonicalize (233 bytes)
      ..<snip>..

       6544 ;; block B2 [9, 13]
       6545 0x00007f2ca8e76f3f: mov 0x50(%rsi),%rdi ; implicit exception: dispatches to 0x00007f2ca8e771ec
       6546 0x00007f2ca8e76f43: cmp $0x0,%edi <<<< 32bit?
       6547 0x00007f2ca8e76f46: mov $0x0,%edi
       6548 0x00007f2ca8e76f4b: jne 0x00007f2ca8e76f56
       6549 0x00007f2ca8e76f51: mov $0x1,%edi ;*invokevirtual isPrimitive {reexecute=0 rethrow=0 return_oop=0}
       6550 ; - java.lang.invoke.MethodTypeForm::canonicalize@10 (line 263)

      -------------

      Reproduce:

      This is not possible to reproduce in the stock VM (though it could happen, albeit with very low probability).

      However, in the new metaspace allocator under development for JDK-8221173 chunk headers are removed from metaspace and therefore the very first Klass* ever to be allocated is located directly at class space start, which may be aligned to 32bit.

      This very first Klass* usually belongs to boolean[].class.

      CDS needs to be off for this to happen.

      To reproduce, sync jdk-sandbox, branch "stuefe-new-metaspace-branch".

      Then apply the following patch to force class space to a rounded address:

      --- a/src/hotspot/share/memory/metaspace.cpp Sat Oct 19 09:26:24 2019 +0200
      +++ b/src/hotspot/share/memory/metaspace.cpp Fri Oct 25 15:40:32 2019 +0200
      @@ -828,6 +828,8 @@
       #ifdef _LP64
           if (using_class_space()) {
             char* base = (char*)align_up(CompressedOops::end(), _reserve_alignment);
      + base= (char*)0xb00000000ULL;
             allocate_metaspace_compressed_klass_ptrs(base, 0);
           }
       #endif // _LP64

      (any address with 32bits set to zero will do).

      and build.

      Then run the jtreg test "java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java", with CDS disabled. It will show an internal error related to isPrimitive() for boolean[].class being wrong.


        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                stuefe Thomas Stuefe
                Reporter:
                stuefe Thomas Stuefe
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: