mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8345422: Fix JNI Checker "in native method" warnings in the debug agent and debugger tests
8344804: Test serviceability/jdwp/AllModulesCommandTest.java times out after JNI check warning Reviewed-by: amenkov, dholmes
This commit is contained in:
parent
67a7b0049d
commit
77cfcee8a1
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
|
||||
static jclass jlM(JNIEnv *env) {
|
||||
return findClass(env, "Ljava/lang/Module;");
|
||||
return findClass(env, "java/lang/Module");
|
||||
}
|
||||
|
||||
static jboolean
|
||||
@ -50,6 +50,11 @@ getName(PacketInputStream *in, PacketOutputStream *out)
|
||||
return JNI_TRUE;
|
||||
}
|
||||
namestr = (jstring)JNI_FUNC_PTR(env, CallObjectMethod) (env, module, method);
|
||||
if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) {
|
||||
JNI_FUNC_PTR(env,ExceptionClear)(env); // keep -Xcheck:jni happy
|
||||
ERROR_MESSAGE(("JNI Exception occurred calling Module.getName()"));
|
||||
EXIT_ERROR(AGENT_ERROR_JNI_EXCEPTION, NULL);
|
||||
}
|
||||
if (namestr != NULL) {
|
||||
name = (char*)JNI_FUNC_PTR(env, GetStringUTFChars)(env, namestr, NULL);
|
||||
} else {
|
||||
@ -78,6 +83,11 @@ getClassLoader(PacketInputStream *in, PacketOutputStream *out)
|
||||
return JNI_TRUE;
|
||||
}
|
||||
loader = JNI_FUNC_PTR(env, CallObjectMethod) (env, module, method);
|
||||
if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) {
|
||||
JNI_FUNC_PTR(env,ExceptionClear)(env); // keep -Xcheck:jni happy
|
||||
ERROR_MESSAGE(("JNI Exception occurred calling ClassLoader.getClassLoader()"));
|
||||
EXIT_ERROR(AGENT_ERROR_JNI_EXCEPTION, NULL);
|
||||
}
|
||||
|
||||
(void)outStream_writeObjectRef(env, out, loader);
|
||||
return JNI_TRUE;
|
||||
|
||||
@ -681,23 +681,14 @@ event_callback(JNIEnv *env, EventInfo *evinfo)
|
||||
bagDestroyBag(eventBag);
|
||||
}
|
||||
|
||||
/* Always restore any exception that was set beforehand. If
|
||||
* there is a pending async exception, StopThread will be
|
||||
* called from threadControl_onEventHandlerExit immediately
|
||||
* below. Depending on VM implementation and state, the async
|
||||
* exception might immediately overwrite the currentException,
|
||||
* or it might be delayed until later. */
|
||||
if (currentException != NULL) {
|
||||
JNI_FUNC_PTR(env,Throw)(env, currentException);
|
||||
} else {
|
||||
JNI_FUNC_PTR(env,ExceptionClear)(env);
|
||||
}
|
||||
/* Clear any exception thrown while handling the event. */
|
||||
JNI_FUNC_PTR(env,ExceptionClear)(env);
|
||||
|
||||
/*
|
||||
* Release thread resources and perform any delayed operations.
|
||||
*/
|
||||
if (thread != NULL) {
|
||||
threadControl_onEventHandlerExit(evinfo->ei, thread, eventBag);
|
||||
threadControl_onEventHandlerExit(evinfo->ei, thread, eventBag, currentException);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -338,6 +338,22 @@ invoker_requestInvoke(jbyte invokeType, jbyte options, jint id,
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
saveGlobalRefHelper(JNIEnv *env, jobject obj, jobject *pobj)
|
||||
{
|
||||
// In order to keep -Xcheck:jni happy, we have to clear any pending
|
||||
// exception before calling saveGlobalRef(). We also need to restore
|
||||
// it for the caller of this function.
|
||||
jthrowable exception = JNI_FUNC_PTR(env,ExceptionOccurred)(env);
|
||||
if (exception != NULL) {
|
||||
JNI_FUNC_PTR(env,ExceptionClear)(env);
|
||||
}
|
||||
saveGlobalRef(env, obj, pobj);
|
||||
if (exception != NULL) {
|
||||
JNI_FUNC_PTR(env,Throw)(env, exception);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
invokeConstructor(JNIEnv *env, InvokeRequest *request)
|
||||
{
|
||||
@ -349,7 +365,7 @@ invokeConstructor(JNIEnv *env, InvokeRequest *request)
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
saveGlobalRefHelper(env, object, &(request->returnValue.l));
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,7 +383,7 @@ invokeStatic(JNIEnv *env, InvokeRequest *request)
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
saveGlobalRefHelper(env, object, &(request->returnValue.l));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -455,7 +471,7 @@ invokeVirtual(JNIEnv *env, InvokeRequest *request)
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
saveGlobalRefHelper(env, object, &(request->returnValue.l));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -545,7 +561,7 @@ invokeNonvirtual(JNIEnv *env, InvokeRequest *request)
|
||||
request->arguments);
|
||||
request->returnValue.l = NULL;
|
||||
if (object != NULL) {
|
||||
saveGlobalRef(env, object, &(request->returnValue.l));
|
||||
saveGlobalRefHelper(env, object, &(request->returnValue.l));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2141,7 +2141,7 @@ doPendingTasks(JNIEnv *env, jthread thread, int pendingInterrupt, jobject pendin
|
||||
|
||||
void
|
||||
threadControl_onEventHandlerExit(EventIndex ei, jthread thread,
|
||||
struct bag *eventBag)
|
||||
struct bag *eventBag, jobject currentException)
|
||||
{
|
||||
ThreadNode *node;
|
||||
JNIEnv *env = getEnv();
|
||||
@ -2178,6 +2178,17 @@ threadControl_onEventHandlerExit(EventIndex ei, jthread thread,
|
||||
// locks when doing that. Thus we got all our node updates done first
|
||||
// and can now exit the threadLock.
|
||||
debugMonitorExit(threadLock);
|
||||
if (currentException != NULL) {
|
||||
// We need to rethrow the exception that was current when we received the
|
||||
// JVMTI event. If there is a pending async exception, StopThread will be
|
||||
// called from doPendingTasks() immediately below. Depending on the VM
|
||||
// implementation and state, the async exception might immediately overwrite
|
||||
// the currentException, or it might be delayed until later.
|
||||
//
|
||||
// Note in order the keep the JNI Checker happy, we had to delay doing this
|
||||
// until now. Otherwise there are complaints when JNI IsVirtualThread is called.
|
||||
JNI_FUNC_PTR(env,Throw)(env, currentException);
|
||||
}
|
||||
doPendingTasks(env, thread, pendingInterrupt, pendingStop);
|
||||
if (pendingStop != NULL) {
|
||||
tossGlobalRef(env, &pendingStop);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -41,8 +41,7 @@ void threadControl_onDisconnect(void);
|
||||
jvmtiError threadControl_popFrames(jthread thread, FrameNumber fnum);
|
||||
|
||||
struct bag *threadControl_onEventHandlerEntry(jbyte sessionID, EventInfo *evinfo, jobject currentException);
|
||||
void threadControl_onEventHandlerExit(EventIndex ei, jthread thread, struct bag *);
|
||||
|
||||
void threadControl_onEventHandlerExit(EventIndex ei, jthread thread, struct bag *, jobject currentException);
|
||||
|
||||
jvmtiError threadControl_suspendThread(jthread thread, jboolean deferred);
|
||||
jvmtiError threadControl_resumeThread(jthread thread, jboolean do_unblock);
|
||||
|
||||
@ -101,13 +101,10 @@ findClass(JNIEnv *env, const char * name)
|
||||
EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"findClass name");
|
||||
}
|
||||
x = JNI_FUNC_PTR(env,FindClass)(env, name);
|
||||
if (x == NULL) {
|
||||
ERROR_MESSAGE(("JDWP Can't find class %s", name));
|
||||
EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
|
||||
}
|
||||
if ( JNI_FUNC_PTR(env,ExceptionCheck)(env) ) {
|
||||
ERROR_MESSAGE(("JDWP Exception occurred finding class %s", name));
|
||||
EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
|
||||
JNI_FUNC_PTR(env,ExceptionClear)(env); // keep -Xcheck:jni happy
|
||||
ERROR_MESSAGE(("JNI Exception occurred finding class %s", name));
|
||||
EXIT_ERROR(AGENT_ERROR_JNI_EXCEPTION,NULL);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
@ -130,15 +127,11 @@ getMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature)
|
||||
EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod signature");
|
||||
}
|
||||
method = JNI_FUNC_PTR(env,GetMethodID)(env, clazz, name, signature);
|
||||
if (method == NULL) {
|
||||
ERROR_MESSAGE(("JDWP Can't find method %s with signature %s",
|
||||
name, signature));
|
||||
EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
|
||||
}
|
||||
if ( JNI_FUNC_PTR(env,ExceptionCheck)(env) ) {
|
||||
ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s",
|
||||
name, signature));
|
||||
EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
|
||||
JNI_FUNC_PTR(env,ExceptionClear)(env); // keep -Xcheck:jni happy
|
||||
ERROR_MESSAGE(("JNI Exception occurred finding method %s with signature %s",
|
||||
name, signature));
|
||||
EXIT_ERROR(AGENT_ERROR_JNI_EXCEPTION,NULL);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
@ -161,15 +154,11 @@ getStaticMethod(JNIEnv *env, jclass clazz, const char * name, const char *signat
|
||||
EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod signature");
|
||||
}
|
||||
method = JNI_FUNC_PTR(env,GetStaticMethodID)(env, clazz, name, signature);
|
||||
if (method == NULL) {
|
||||
ERROR_MESSAGE(("JDWP Can't find method %s with signature %s",
|
||||
name, signature));
|
||||
EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
|
||||
}
|
||||
if ( JNI_FUNC_PTR(env,ExceptionCheck)(env) ) {
|
||||
JNI_FUNC_PTR(env,ExceptionClear)(env); // keep -Xcheck:jni happy
|
||||
ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s",
|
||||
name, signature));
|
||||
EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL);
|
||||
name, signature));
|
||||
EXIT_ERROR(AGENT_ERROR_JNI_EXCEPTION,NULL);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
@ -116,6 +116,7 @@ Java_nsk_share_ReferringObject_createJNILocalReferenceNative(JNIEnv *env,
|
||||
env->ThrowNew(
|
||||
env->FindClass("nsk/share/TestJNIError"),
|
||||
"NewLocalRef return null");
|
||||
return;
|
||||
}
|
||||
|
||||
klass = env->GetObjectClass(createWicket);
|
||||
@ -123,8 +124,11 @@ Java_nsk_share_ReferringObject_createJNILocalReferenceNative(JNIEnv *env,
|
||||
// notify another thread that JNI local reference has been created
|
||||
env->CallVoidMethod(createWicket,
|
||||
env->GetMethodID(klass, "unlock", "()V"));
|
||||
if (env->ExceptionCheck()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// wait till JNI local reference can be released (it will heppen then we will leave the method)
|
||||
// wait till JNI local reference can be released (it will happen then we will leave the method)
|
||||
env->CallVoidMethod(deleteWicket,
|
||||
env->GetMethodID(klass, "waitFor", "()V"));
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,6 +33,10 @@ static void logMessage(JNIEnv *env, jobject thisObject, jstring message)
|
||||
env->CallVoidMethod(thisObject,
|
||||
env->GetMethodID(klass, "log", "(Ljava/lang/String;)V"),
|
||||
message);
|
||||
if (env->ExceptionOccurred()) {
|
||||
env->ExceptionDescribe();
|
||||
env->FatalError("ERROR: Failed to log message.");
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
|
||||
@ -66,6 +66,7 @@ This method executes JNI analog for following Java code:
|
||||
env->ThrowNew(
|
||||
env->FindClass("nsk/share/TestJNIError"),
|
||||
"MonitorEnter return non-zero");
|
||||
return;
|
||||
}
|
||||
|
||||
thisObjectClass = env->GetObjectClass(thisObject);
|
||||
@ -78,6 +79,9 @@ This method executes JNI analog for following Java code:
|
||||
|
||||
env->CallVoidMethod(wicketObject,
|
||||
env->GetMethodID(wicketClass, "unlockAll", "()V"));
|
||||
if (env->ExceptionOccurred()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// step2.waitFor()
|
||||
field = env->GetFieldID(thisObjectClass, "step2", "Lnsk/share/Wicket;");
|
||||
@ -85,6 +89,9 @@ This method executes JNI analog for following Java code:
|
||||
|
||||
env->CallVoidMethod(wicketObject,
|
||||
env->GetMethodID(wicketClass, "waitFor", "()V"));
|
||||
if (env->ExceptionOccurred()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// readyWicket.unlock()
|
||||
field = env->GetFieldID(thisObjectClass, "readyWicket", "Lnsk/share/Wicket;");
|
||||
@ -92,6 +99,9 @@ This method executes JNI analog for following Java code:
|
||||
|
||||
env->CallVoidMethod(wicketObject,
|
||||
env->GetMethodID(wicketClass, "unlock", "()V"));
|
||||
if (env->ExceptionOccurred()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// inner.lock()
|
||||
field = env->GetFieldID(thisObjectClass, "inner", "Lnsk/share/locks/DeadlockLocker;");
|
||||
@ -100,8 +110,14 @@ This method executes JNI analog for following Java code:
|
||||
|
||||
env->CallVoidMethod(innerObject,
|
||||
env->GetMethodID(deadlockLockerClass, "lock", "()V"));
|
||||
if (env->ExceptionOccurred()) {
|
||||
return;
|
||||
}
|
||||
|
||||
success = env->MonitorExit(thisObject);
|
||||
if (env->ExceptionOccurred()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (success != 0)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user