From 73fd01800e1ad42629d72122561d512b2ab0a939 Mon Sep 17 00:00:00 2001 From: Gengchen Tuo Date: Tue, 16 Jul 2024 09:42:45 -0400 Subject: [PATCH] Add JVMTI VirtualThreadDestroy Event Currently destroyThreadData() is hooked onto the VirtualThreadEnd event which is called before the event callback. In JDWP, the agent uses TLS to associate nodes in the running thread list. Clearing TLS before the event callback makes the agent lose track of the node thus failed to remove existed virtual threads from the list. This commit adds JVMTI VirtualThreadDestroy event which is triggered after VirtualThreadEnd and jvmtiHookVirtualThreadDestroy() is hooked onto VirtualThreadDestroy event. Fixes: https://github.com/ibmruntimes/Semeru-Runtimes/issues/80 https://github.com/eclipse-openj9/openj9/issues/19759 Signed-off-by: Gengchen Tuo --- runtime/include/ibmjvmti.h | 1 + runtime/j9vm/javanextvmi.cpp | 1 + runtime/jvmti/jvmtiExtensionMechanism.c | 12 ++++++++++++ runtime/jvmti/jvmtiHelpers.cpp | 1 + runtime/jvmti/jvmtiHook.c | 4 ++-- runtime/nls/j9ti/jvmti.nls | 7 +++++++ runtime/oti/j9consts.h | 2 +- runtime/oti/j9vm.hdf | 10 ++++++++++ runtime/oti/jvmtiInternal.h | 1 + 9 files changed, 36 insertions(+), 3 deletions(-) diff --git a/runtime/include/ibmjvmti.h b/runtime/include/ibmjvmti.h index 1988bfe89f3..8cc1f2af1b1 100644 --- a/runtime/include/ibmjvmti.h +++ b/runtime/include/ibmjvmti.h @@ -105,6 +105,7 @@ #define COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_MOUNT "com.sun.hotspot.events.VirtualThreadMount" #define COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_UNMOUNT "com.sun.hotspot.events.VirtualThreadUnmount" +#define COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY "com.sun.hotspot.events.VirtualThreadDestroy" #define OPENJ9_EVENT_VM_CHECKPOINT "openj9.event.VMCheckpoint" #define OPENJ9_EVENT_VM_RESTORE "openj9.event.VMRestore" diff --git a/runtime/j9vm/javanextvmi.cpp b/runtime/j9vm/javanextvmi.cpp index 45d6f80b6fc..6308573ea75 100644 --- a/runtime/j9vm/javanextvmi.cpp +++ b/runtime/j9vm/javanextvmi.cpp @@ -724,6 +724,7 @@ JVM_VirtualThreadEnd(JNIEnv *env, jobject vthread) TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_END(vm->hookInterface, currentThread); setContinuationStateToLastUnmount((J9VMThread *)env, vthread); virtualThreadUnmountBegin(env, vthread); + TRIGGER_J9HOOK_VM_VIRTUAL_THREAD_DESTROY(vm->hookInterface, currentThread); vmFuncs->internalExitVMToJNI(currentThread); diff --git a/runtime/jvmti/jvmtiExtensionMechanism.c b/runtime/jvmti/jvmtiExtensionMechanism.c index fb22b0119dd..d88d23299fd 100644 --- a/runtime/jvmti/jvmtiExtensionMechanism.c +++ b/runtime/jvmti/jvmtiExtensionMechanism.c @@ -366,6 +366,12 @@ static const jvmtiParamInfo jvmtiVirtualThreadUnmount_params[] = { { "jni_env", JVMTI_KIND_IN_PTR, JVMTI_TYPE_JNIENV, JNI_FALSE }, { "thread", JVMTI_KIND_IN, JVMTI_TYPE_JTHREAD, JNI_FALSE } }; + +/* (jvmtiEnv *jvmti_env, jthread thread) */ +static const jvmtiParamInfo jvmtiVirtualThreadDestroy_params[] = { + { "jni_env", JVMTI_KIND_IN_PTR, JVMTI_TYPE_JNIENV, JNI_FALSE }, + { "thread", JVMTI_KIND_IN, JVMTI_TYPE_JTHREAD, JNI_FALSE } +}; #endif /* JAVA_SPEC_VERSION >= 19 */ #if JAVA_SPEC_VERSION >= 19 @@ -906,6 +912,12 @@ static const J9JVMTIExtensionEventInfo J9JVMTIExtensionEventInfoTable[] = { J9NLS_JVMTI_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_UNMOUNT, SIZE_AND_TABLE(jvmtiVirtualThreadUnmount_params), }, + { + J9JVMTI_EVENT_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY, + COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY, + J9NLS_JVMTI_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY, + SIZE_AND_TABLE(jvmtiVirtualThreadDestroy_params), + }, #endif /* JAVA_SPEC_VERSION >= 19 */ #if defined(J9VM_OPT_CRIU_SUPPORT) { diff --git a/runtime/jvmti/jvmtiHelpers.cpp b/runtime/jvmti/jvmtiHelpers.cpp index a39e0c8b5e1..99b4bfbadda 100644 --- a/runtime/jvmti/jvmtiHelpers.cpp +++ b/runtime/jvmti/jvmtiHelpers.cpp @@ -85,6 +85,7 @@ static const UDATA reasonCodeFromJVMTIEvent[] = { J9_JNI_OFFLOAD_SWITCH_J9JVMTI_GC_CYCLE_FINISH, /* J9JVMTI_EVENT_COM_IBM_GARBAGE_COLLECTION_CYCLE_FINISH */ J9_JNI_OFFLOAD_SWITCH_J9JVMTI_VIRTUAL_THREAD_MOUNT, /* J9JVMTI_EVENT_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_MOUNT */ J9_JNI_OFFLOAD_SWITCH_J9JVMTI_VIRTUAL_THREAD_UNMOUNT, /* J9JVMTI_EVENT_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_UNMOUNT */ + J9_JNI_OFFLOAD_SWITCH_J9JVMTI_VIRTUAL_THREAD_DESTROY, /* J9JVMTI_EVENT_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY */ J9_JNI_OFFLOAD_SWITCH_J9JVMTI_EVENT_OPENJ9_VM_CHECKPOINT, /* J9JVMTI_EVENT_OPENJ9_VM_CHECKPOINT */ J9_JNI_OFFLOAD_SWITCH_J9JVMTI_EVENT_OPENJ9_VM_RESTORE, /* J9JVMTI_EVENT_OPENJ9_VM_RESTORE */ }; diff --git a/runtime/jvmti/jvmtiHook.c b/runtime/jvmti/jvmtiHook.c index fa52875bcb1..25e6b6880e7 100644 --- a/runtime/jvmti/jvmtiHook.c +++ b/runtime/jvmti/jvmtiHook.c @@ -968,7 +968,7 @@ unhookAllEvents(J9JVMTIEnv * j9env) hookUnregister(vmHook, J9HOOK_VM_THREAD_DESTROY, jvmtiHookThreadDestroy, NULL, j9env); #if JAVA_SPEC_VERSION >= 19 - hookUnregister(vmHook, J9HOOK_VM_VIRTUAL_THREAD_END, jvmtiHookVirtualThreadDestroy, NULL, j9env); + hookUnregister(vmHook, J9HOOK_VM_VIRTUAL_THREAD_DESTROY, jvmtiHookVirtualThreadDestroy, NULL, j9env); #endif /* JAVA_SPEC_VERSION >= 19 */ hookUnregister(vmHook, J9HOOK_VM_POP_FRAMES_INTERRUPT, jvmtiHookPopFramesInterrupt, NULL, j9env); @@ -987,7 +987,7 @@ hookRequiredEvents(J9JVMTIEnv * j9env) } #if JAVA_SPEC_VERSION >= 19 - if (hookRegister(vmHook, J9HOOK_VM_VIRTUAL_THREAD_END, jvmtiHookVirtualThreadDestroy, OMR_GET_CALLSITE(), j9env)) { + if (hookRegister(vmHook, J9HOOK_VM_VIRTUAL_THREAD_DESTROY, jvmtiHookVirtualThreadDestroy, OMR_GET_CALLSITE(), j9env)) { return 1; } #endif /* JAVA_SPEC_VERSION >= 19 */ diff --git a/runtime/nls/j9ti/jvmti.nls b/runtime/nls/j9ti/jvmti.nls index 8d1c3f4c153..b797fe448e2 100644 --- a/runtime/nls/j9ti/jvmti.nls +++ b/runtime/nls/j9ti/jvmti.nls @@ -639,6 +639,13 @@ J9NLS_JVMTI_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_UNMOUNT.system_action=None J9NLS_JVMTI_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_UNMOUNT.user_response=None # END NON-TRANSLATABLE +J9NLS_JVMTI_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY=Free native resources after a virtual thread ends. +# START NON-TRANSLATABLE +J9NLS_JVMTI_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY.explanation=Internationalized description of a JVMTI extension +J9NLS_JVMTI_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY.system_action=None +J9NLS_JVMTI_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY.user_response=None +# END NON-TRANSLATABLE + J9NLS_J9JVMTI_EVENT_OPENJ9_VM_CHECKPOINT=At VM pre-checkpoint phase. # START NON-TRANSLATABLE J9NLS_J9JVMTI_EVENT_OPENJ9_VM_CHECKPOINT.explanation=VM is preparing to take a checkpoint. diff --git a/runtime/oti/j9consts.h b/runtime/oti/j9consts.h index e6b60957c3a..98cb718c50d 100644 --- a/runtime/oti/j9consts.h +++ b/runtime/oti/j9consts.h @@ -795,7 +795,7 @@ extern "C" { #define J9_JNI_OFFLOAD_SWITCH_JVMTI_MONITOR_CONTENDED_ENTERED 0x30 #define J9_JNI_OFFLOAD_SWITCH_J9JVMTI_VIRTUAL_THREAD_MOUNT 0x31 #define J9_JNI_OFFLOAD_SWITCH_J9JVMTI_VIRTUAL_THREAD_UNMOUNT 0x32 -/* 0x33 Reserved for JVMTI event */ +#define J9_JNI_OFFLOAD_SWITCH_J9JVMTI_VIRTUAL_THREAD_DESTROY 0x33 #define J9_JNI_OFFLOAD_SWITCH_JVMTI_RESOURCE_EXHAUSTED 0x34 #define J9_JNI_OFFLOAD_SWITCH_JVMTI_GC_START 0x35 #define J9_JNI_OFFLOAD_SWITCH_JVMTI_GC_FINISH 0x36 diff --git a/runtime/oti/j9vm.hdf b/runtime/oti/j9vm.hdf index ba751eae78a..fd67b034ee6 100644 --- a/runtime/oti/j9vm.hdf +++ b/runtime/oti/j9vm.hdf @@ -1383,6 +1383,16 @@ typedef UDATA (* lookupNativeAddressCallback)(struct J9VMThread *currentThread, + + J9HOOK_VM_VIRTUAL_THREAD_DESTROY + + Triggered after J9HOOK_VM_VIRTUAL_THREAD_END to free native resources. + currentThread->threadObject is the virtual thread at the point of trigger. + + J9VMVirtualThreadDestroyEvent + + + J9HOOK_VM_CRIU_CHECKPOINT Triggered at the end of CRIU checkpoint, just before CRIU dump diff --git a/runtime/oti/jvmtiInternal.h b/runtime/oti/jvmtiInternal.h index e317a78a2ba..32473d0ec68 100644 --- a/runtime/oti/jvmtiInternal.h +++ b/runtime/oti/jvmtiInternal.h @@ -43,6 +43,7 @@ typedef enum { J9JVMTI_EVENT_COM_IBM_GARBAGE_COLLECTION_CYCLE_FINISH, J9JVMTI_EVENT_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_MOUNT, J9JVMTI_EVENT_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_UNMOUNT, + J9JVMTI_EVENT_COM_SUN_HOTSPOT_EVENTS_VIRTUAL_THREAD_DESTROY, J9JVMTI_EVENT_OPENJ9_VM_CHECKPOINT, J9JVMTI_EVENT_OPENJ9_VM_RESTORE, J9JVMTI_AFTER_LAST_EXTENSION_EVENT