8200195: serviceability/jvmti/FieldAccessWatch/FieldAccessWatch.java crashes with "assert(thread->thread_state() == _thread_in_native) failed: coming from wrong thread state"

Reviewed-by: sspitsyn, cjplummer
This commit is contained in:
Alex Menkov 2018-04-10 15:33:11 -07:00
parent 4ef7c919a2
commit f8f1f3daba

View File

@ -35,7 +35,6 @@ extern "C" {
static jvmtiEnv *jvmti = NULL; static jvmtiEnv *jvmti = NULL;
// valid while a test is executed // valid while a test is executed
static JNIEnv *javaEnv = NULL;
static jobject testResultObject = NULL; static jobject testResultObject = NULL;
static jclass testResultClass = NULL; static jclass testResultClass = NULL;
@ -46,7 +45,8 @@ static void reportError(const char *msg, int err) {
// logs the notification and updates currentTestResult // logs the notification and updates currentTestResult
static void handleNotification(jmethodID method, static void handleNotification(JNIEnv *jni_env,
jmethodID method,
jfieldID field, jfieldID field,
jclass field_klass, jclass field_klass,
int modified, int modified,
@ -92,21 +92,21 @@ static void handleNotification(jmethodID method,
csig, mname, mgensig, modified ? "modified" : "accessed", name, (int)location); csig, mname, mgensig, modified ? "modified" : "accessed", name, (int)location);
// set TestResult // set TestResult
if (javaEnv != NULL && testResultObject != NULL && testResultClass != NULL) { if (testResultObject != NULL && testResultClass != NULL) {
jfieldID fieldID; jfieldID fieldID;
// field names in TestResult are "<field_name>_access"/"<field_name>_modify" // field names in TestResult are "<field_name>_access"/"<field_name>_modify"
char *fieldName = (char *)malloc(strlen(name) + 16); char *fieldName = (char *)malloc(strlen(name) + 16);
strcpy(fieldName, name); strcpy(fieldName, name);
strcat(fieldName, modified ? "_modify" : "_access"); strcat(fieldName, modified ? "_modify" : "_access");
fieldID = (*javaEnv)->GetFieldID(javaEnv, testResultClass, fieldName, "Z"); fieldID = (*jni_env)->GetFieldID(jni_env, testResultClass, fieldName, "Z");
if (fieldID != NULL) { if (fieldID != NULL) {
(*javaEnv)->SetBooleanField(javaEnv, testResultObject, fieldID, JNI_TRUE); (*jni_env)->SetBooleanField(jni_env, testResultObject, fieldID, JNI_TRUE);
} else { } else {
// the field is not interesting for the test // the field is not interesting for the test
} }
// clear any possible exception // clear any possible exception
(*javaEnv)->ExceptionClear(javaEnv); (*jni_env)->ExceptionClear(jni_env);
free(fieldName); free(fieldName);
} }
@ -179,7 +179,7 @@ onFieldAccess(jvmtiEnv *jvmti_env,
jobject object, jobject object,
jfieldID field) jfieldID field)
{ {
handleNotification(method, field, field_klass, 0, location); handleNotification(jni_env, method, field, field_klass, 0, location);
} }
@ -195,7 +195,7 @@ onFieldModification(jvmtiEnv *jvmti_env,
char signature_type, char signature_type,
jvalue new_value) jvalue new_value)
{ {
handleNotification(method, field, field_klass, 1, location); handleNotification(jni_env, method, field, field_klass, 1, location);
if (signature_type == 'L') { if (signature_type == 'L') {
jobject newObject = new_value.l; jobject newObject = new_value.l;
@ -282,9 +282,8 @@ Java_FieldAccessWatch_initWatchers(JNIEnv *env, jclass thisClass, jclass cls, jo
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_FieldAccessWatch_startTest(JNIEnv *env, jclass thisClass, jobject testResults) Java_FieldAccessWatch_startTest(JNIEnv *env, jclass thisClass, jobject testResults)
{ {
javaEnv = env; testResultObject = (*env)->NewGlobalRef(env, testResults);
testResultObject = (*javaEnv)->NewGlobalRef(javaEnv, testResults); testResultClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, testResultObject));
testResultClass = (jclass)(*javaEnv)->NewGlobalRef(javaEnv, (*javaEnv)->GetObjectClass(javaEnv, testResultObject));
return JNI_TRUE; return JNI_TRUE;
} }