ADDITIONAL SYSTEM INFORMATION :
Linux, JDK 19-ea+23-1706
A DESCRIPTION OF THE PROBLEM :
Using the Foreign Function & Memory API to call a native C++ function which calls back into the JVM concurrently (at least two C++ threads) causes the JVM to crash. The same program (modulo some changes to make it compilable with JDK 19) worked on JVM 18.
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007fec8d25e842, pid=7636, tid=7655
#
# JRE version: OpenJDK Runtime Environment (19.0+23) (build 19-ea+23-1706)
# Java VM: OpenJDK 64-Bit Server VM (19-ea+23-1706, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V [libjvm.so+0x85e842] java_lang_Thread::set_thread_status(oopDesc*, JavaThreadStatus)+0x22
--------------- S U M M A R Y ------------
Command Line: --enable-preview --enable-native-access=ALL-UNNAMED JavaClass
Host: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz, 8 cores, 7G, Manjaro Linux
Time: Wed May 25 13:58:14 2022 CEST elapsed time: 0.110217 seconds (0d 0h 0m 0s)
--------------- T H R E A D ---------------
Current thread (0x00007fec18000bf0): JavaThread "<no-name - thread is attaching>"
[error occurred during error reporting (printing current thread), id 0xb, SIGSEGV (0xb) at pc=0x00007fec8d25e78c]
Stack: [0x00007fec23801000,0x00007fec24000000], sp=0x00007fec23ffe160, free space=8180k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.so+0x85e842] java_lang_Thread::set_thread_status(oopDesc*, JavaThreadStatus)+0x22
V [libjvm.so+0xc4132b] ObjectMonitor::INotify(JavaThread*)+0x13b
V [libjvm.so+0xc4275f] ObjectMonitor::notifyAll(JavaThread*)+0x8f
V [libjvm.so+0x82dbee] InstanceKlass::set_initialization_state_and_notify(InstanceKlass::ClassState, JavaThread*)+0xae
V [libjvm.so+0x836ea8] InstanceKlass::initialize_impl(JavaThread*)+0x738
V [libjvm.so+0xad5a9a] LinkResolver::resolve_static_call(CallInfo&, LinkInfo const&, bool, JavaThread*)+0x16a
V [libjvm.so+0xad64cb] LinkResolver::resolve_invoke(CallInfo&, Handle, constantPoolHandle const&, int, Bytecodes::Code, JavaThread*)+0x2bb
V [libjvm.so+0x8538b7] InterpreterRuntime::resolve_invoke(JavaThread*, Bytecodes::Code)+0x177
V [libjvm.so+0x853e37] InterpreterRuntime::resolve_from_cache(JavaThread*, Bytecodes::Code)+0x37
j java.lang.Thread.genThreadName()Ljava/lang/String;+13 java.base@19-ea
j java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;)V+2 java.base@19-ea
v ~StubRoutines::call_stub 0x00007fec78537cc6
V [libjvm.so+0x8589f5] JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, JavaThread*)+0x315
V [libjvm.so+0x85a01a] JavaCalls::call_special(JavaValue*, Handle, Klass*, Symbol*, Symbol*, Handle, Handle, JavaThread*)+0x1aa
V [libjvm.so+0xe11612] JavaThread::allocate_threadObj(Handle, char const*, bool, JavaThread*)+0xc2
V [libjvm.so+0x9042aa] attach_current_thread.part.0+0x19a
V [libjvm.so+0xe3e02b] ProgrammableUpcallHandler::on_entry(OptimizedEntryBlob::FrameData*)+0x15b
v blob 0x00007fec78661b91
C [libffm.so+0x3514] f(char const* (*)())+0x1b
C [libffm.so+0x3eb8] void std::__invoke_impl<void, void (*)(char const* (*)()), char const* (*)()>(std::__invoke_other, void (*&&)(char const* (*)()), char const* (*&&)())+0x34
C [libffm.so+0x3e2d] std::__invoke_result<void (*)(char const* (*)()), char const* (*)()>::type std::__invoke<void (*)(char const* (*)()), char const* (*)()>(void (*&&)(char const* (*)()), char const* (*&&)())+0x37
C [libffm.so+0x3d9d] void std::thread::_Invoker<std::tuple<void (*)(char const* (*)()), char const* (*)()> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>)+0x43
C [libffm.so+0x3d56] std::thread::_Invoker<std::tuple<void (*)(char const* (*)()), char const* (*)()> >::operator()()+0x18
C [libffm.so+0x3d3a] std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(char const* (*)()), char const* (*)()> > >::_M_run()+0x1c
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j java.lang.Thread.genThreadName()Ljava/lang/String;+13 java.base@19-ea
j java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;)V+2 java.base@19-ea
v ~StubRoutines::call_stub 0x00007fec78537cc6
siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000018
[abridged -- see hs_err.txt in attachment]
REGRESSION : Last worked in version 18.0.1
FREQUENCY : often
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
$ g++ -fPIC -shared -o libffm.so nativemethod.cpp
$ javac --enable-preview -source 19 JavaClass.java
$ LD_LIBRARY_PATH=. java --enable-preview --enable-native-access=ALL-UNNAMED JavaClass
---------- BEGIN SOURCE ----------
nativemethod.cpp:
#include <iostream>
#include <thread>
using namespace std;
extern "C" {
void nativeMethod(const char* (*) ());
}
void f(const char* getMessage()) {
for (auto i = 0; i < 100; ++i)
cout << getMessage() << endl;
};
void nativeMethod(const char* getMessage()) {
auto t1 = thread{f, getMessage};
auto t2 = thread{f, getMessage};
t1.join();
t2.join();
}
JavaClass.java:
import java.lang.foreign.Addressable;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemorySession;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import static java.lang.foreign.SegmentAllocator.implicitAllocator;
public class JavaClass {
static {
System.loadLibrary("ffm");
}
public static Addressable getMessage() {
return implicitAllocator().allocateUtf8String("Hello World!").address();
}
public static void main(String... args) {
try {
var linker = Linker.nativeLinker();
var symbolLookup = SymbolLookup.loaderLookup();
var symbol = symbolLookup.lookup("nativeMethod").orElseThrow();
var functionDesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
var methodHandle = linker.downcallHandle(symbol, functionDesc);
var upcallMethodType = MethodType.methodType(Addressable.class);
var upcallFunctionDesc = FunctionDescriptor.of(ValueLayout.ADDRESS);
var upcallMethodHandle = MethodHandles.lookup().findStatic(JavaClass.class, "getMessage", upcallMethodType);
var upcallSymbol = linker.upcallStub(upcallMethodHandle, upcallFunctionDesc, MemorySession.openImplicit());
methodHandle.invoke(upcallSymbol);
} catch (Throwable e) {
System.out.println(e);
}
}
}