Skip to content

Commit

Permalink
Fix jvmtiGetThreadInfo
Browse files Browse the repository at this point in the history
Set J9JavaVM->vthreadGroup in stdinit.c::standardInit to remove the
recursive dependency with JVMTI event callbacks, which causes an
infinite loop.

Closes: #16229

Signed-off-by: Babneet Singh <sbabneet@ca.ibm.com>
  • Loading branch information
babsingh committed Nov 15, 2022
1 parent 167a660 commit 0bdd6f2
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 44 deletions.
19 changes: 19 additions & 0 deletions runtime/jcl/common/stdinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,25 @@ standardInit(J9JavaVM *vm, char *dllName)
(void)(*(JNIEnv*)vmThread)->GetStaticFieldID((JNIEnv*)vmThread, clazz, "helpers", "Lcom/ibm/jit/JITHelpers;");
(*(JNIEnv*)vmThread)->DeleteLocalRef((JNIEnv*)vmThread, clazz);
}

#if JAVA_SPEC_VERSION >= 19
clazz = (*(JNIEnv*)vmThread)->FindClass((JNIEnv*)vmThread, "java/lang/Thread$Constants");
if (NULL != clazz) {
jfieldID id = (*(JNIEnv*)vmThread)->GetStaticFieldID((JNIEnv*)vmThread, clazz, "VTHREAD_GROUP", "Ljava/lang/ThreadGroup;");
if (NULL != id) {
jobject tempGroup = (*(JNIEnv*)vmThread)->GetStaticObjectField((JNIEnv*)vmThread, clazz, id);
if (NULL != tempGroup) {
vm->vthreadGroup = (jobject)(*(JNIEnv*)vmThread)->NewGlobalRef((JNIEnv*)vmThread, tempGroup);
}
}
(*(JNIEnv*)vmThread)->DeleteLocalRef((JNIEnv*)vmThread, clazz);
if (NULL == vm->vthreadGroup) {
goto _fail;
}
} else {
goto _fail;
}
#endif /* JAVA_SPEC_VERSION >= 19 */
#endif /* !J9VM_IVE_RAW_BUILD */
}
#endif
Expand Down
43 changes: 1 addition & 42 deletions runtime/jvmti/jvmtiThread.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,48 +522,7 @@ jvmtiGetThreadInfo(jvmtiEnv *env,
/* For virtual threads, check its state. */
if (JVMTI_VTHREAD_STATE_TERMINATED != J9VMJAVALANGVIRTUALTHREAD_STATE(currentThread, threadObject)) {
/* The thread group of a virtual thread is always j.l.Thread$Constants.VTHREAD_GROUP. */
JNIEnv *jniEnv = (JNIEnv *)currentThread;
jclass constants = vm->jlThreadConstants;
jfieldID id = vm->vthreadGroupID;
jobject tempGroup = NULL;

vm->internalVMFunctions->internalExitVMToJNI(currentThread);
if (NULL == constants) {
/* Cache the class. */
jclass localRef = (*jniEnv)->FindClass(jniEnv, "java/lang/Thread$Constants");
Assert_JVMTI_notNull(localRef);
constants = (jclass)((*jniEnv)->NewGlobalRef(jniEnv, localRef));
if (NULL != constants) {
vm->jlThreadConstants = constants;
} else {
rc = JVMTI_ERROR_OUT_OF_MEMORY;
}
}

if ((NULL != constants) && (NULL == id)) {
/* Cache the field id. */
id = (*jniEnv)->GetStaticFieldID(jniEnv, constants, "VTHREAD_GROUP", "Ljava/lang/ThreadGroup;");
if (NULL != id) {
vm->vthreadGroupID = id;
} else {
rc = JVMTI_ERROR_OUT_OF_MEMORY;
}
}

if ((NULL != constants) && (NULL != id)) {
tempGroup = (*jniEnv)->GetStaticObjectField(jniEnv, constants, id);
Assert_JVMTI_notNull(tempGroup);
}

/* VM access is required before invoking releaseVMThread. */
vm->internalVMFunctions->internalEnterVMFromJNI(currentThread);
if (JVMTI_ERROR_OUT_OF_MEMORY == rc) {
j9mem_free_memory(name);
goto release;
}

group = J9_JNI_UNWRAP_REFERENCE(tempGroup);
threadObject = (NULL == thread) ? targetThread->threadObject : J9_JNI_UNWRAP_REFERENCE(thread);
group = J9_JNI_UNWRAP_REFERENCE(vm->vthreadGroup);
}
} else {
/* For platform threads, a NULL vmthread indicates that a thread is terminated. */
Expand Down
3 changes: 1 addition & 2 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -5799,8 +5799,7 @@ typedef struct J9JavaVM {
omrthread_monitor_t tlsFinalizersMutex;
struct J9Pool *tlsPool;
omrthread_monitor_t tlsPoolMutex;
jclass jlThreadConstants;
jfieldID vthreadGroupID;
jobject vthreadGroup;
#endif /* JAVA_SPEC_VERSION >= 19 */
} J9JavaVM;

Expand Down

0 comments on commit 0bdd6f2

Please sign in to comment.