JDK-8303416 : [lworld] Fix JVM crash at Unsafe_FinishPrivateBuffer
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: repo-valhalla
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2023-03-01
  • Updated: 2023-03-13
  • Resolved: 2023-03-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
repo-valhallaFixed
Related Reports
Relates :  
Description
JVM crash with following assertion failure:
```
#  Internal Error (valhalla/src/hotspot/share/prims/unsafe.cpp:388), pid=29517, tid=29518
#  assert(v->mark().is_larval_state()) failed: must be a larval value
#
# JRE version: OpenJDK Runtime Environment (21.0) (fastdebug build 21-internal-git-05e4d0dba)
# Java VM: OpenJDK 64-Bit Server VM (fastdebug 21-internal-git-05e4d0dba, mixed mode, compressed oops, compressed class ptrs, g1 gc, linux-aarch64)
# Problematic frame:
# V  [libjvm.so+0x1a92a64]  Unsafe_FinishPrivateBuffer+0xc0
```
When running following java test:
```
import java.lang.reflect.*;

import jdk.internal.misc.Unsafe;

public class Test {
    private static int LENGTH = 10000;
    static byte[] arr = new byte[LENGTH];

    static {
        for (int i = 0; i < LENGTH; i++) {
            arr[i] = (byte) i;
        }
    }

    public static byte test(byte b) {
        Value obj = new Value();
        obj = Unsafe.getUnsafe().makePrivateBuffer(obj);
        Unsafe.getUnsafe().putByte(obj, obj.offset, b);
        obj = Unsafe.getUnsafe().finishPrivateBuffer(obj);
        return Unsafe.getUnsafe().getByte(obj, obj.offset);
    }

    public static void main(String[] args) {
        byte actual = 0;
        for (int i = 0; i < LENGTH; i++) {
            actual += test(arr[i]);
        }
    }

    primitive static class Value {
        byte field = 0;
        static long offset = fieldOffset();

        private static long fieldOffset() {
            try {
                var f = Value.class.getDeclaredField("field");
                return Unsafe.getUnsafe().objectFieldOffset(f);
            } catch (Exception e) {
                System.out.println(e);
            }
            return -1L;
        }
    }
}
```
The root cause is the allocated buffer created by "makePrivateBuffer" is optimized to the default oop of the primitive class in C2 compiler. The optimization miss the larval state of the allocated buffer, which is not marked to the default oop.  The assertion happens when the "finishPrivateBuffer" is compiled by interpreter, and the failure happens when it checks whether the expected larval state is set.

Comments
A pull request was submitted for review. URL: https://git.openjdk.org/valhalla/pull/828 Date: 2023-03-02 09:00:41 +0000
02-03-2023

Sounds good, I can have a look at the PR once it's ready.
01-03-2023

Thanks! So I will push the patch soon as a separate fix. And we can re-see this issue once JDK-8239003 is fixed. And I didn't see any conflict with the patch you pointed out. Thanks!
01-03-2023

Sure, fixing this independently is fine. I just wanted to point out that there a probably more issues. And maybe you can verify that your fix does not conflict with JDK-8293800 (see https://github.com/openjdk/valhalla/compare/lworld...TobiHartmann:valhalla:JDK-8293800) which I'm hopefully integrating soon. Thanks!
01-03-2023

Thanks for looking at this issue! I have prepared a patch to fix it by adding back the larval state if the private buffer is optimized out with the default oop as the replacement. And it seems it can also be fixed once JDK-8239003 is fixed. As I noticed that JDK-8239003 is not opened yet, do you think it's necessary to fix this issue temporarily now?
01-03-2023

This is related to JDK-8239003. The private buffer code is currently broken.
01-03-2023