8290482: Update JNI Specification of DestroyJavaVM for better alignment with JLS, JVMS, and Java SE API Specifications

Reviewed-by: rehn, coleenp
This commit is contained in:
David Holmes 2022-09-27 23:57:32 +00:00
parent f8d9fa8873
commit e5b65c40ea
6 changed files with 111 additions and 4 deletions

View File

@ -101,7 +101,7 @@
#include "jvmci/jvmciCompiler.hpp"
#endif
static jint CurrentVersion = JNI_VERSION_19;
static jint CurrentVersion = JNI_VERSION_20;
#if defined(_WIN32) && !defined(USE_VECTORED_EXCEPTION_HANDLING)
extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* );
@ -3754,9 +3754,16 @@ static jint JNICALL jni_DestroyJavaVM_inner(JavaVM *vm) {
return res;
}
// Since this is not a JVM_ENTRY we have to set the thread state manually before entering.
JavaThread* thread = JavaThread::current();
// Make sure we are actually in a newly attached thread, with no
// existing Java frame.
if (thread->has_last_Java_frame()) {
return JNI_ERR;
}
// Since this is not a JVM_ENTRY we have to set the thread state manually before entering.
// We are going to VM, change W^X state to the expected one.
MACOS_AARCH64_ONLY(WXMode oldmode = thread->enable_wx(WXWrite));

View File

@ -1166,6 +1166,7 @@ jboolean Threads::is_supported_jni_version(jint version) {
if (version == JNI_VERSION_9) return JNI_TRUE;
if (version == JNI_VERSION_10) return JNI_TRUE;
if (version == JNI_VERSION_19) return JNI_TRUE;
if (version == JNI_VERSION_20) return JNI_TRUE;
return JNI_FALSE;
}

View File

@ -1991,6 +1991,7 @@ JNI_OnUnload(JavaVM *vm, void *reserved);
#define JNI_VERSION_9 0x00090000
#define JNI_VERSION_10 0x000a0000
#define JNI_VERSION_19 0x00130000
#define JNI_VERSION_20 0x00140000
#ifdef __cplusplus
} /* extern "C" */

View File

@ -27,12 +27,12 @@
*/
public class JniVersion {
public static final int JNI_VERSION_19 = 0x00130000;
public static final int JNI_VERSION_20 = 0x00140000;
public static void main(String... args) throws Exception {
System.loadLibrary("JniVersion");
int res = getJniVersion();
if (res != JNI_VERSION_19) {
if (res != JNI_VERSION_20) {
throw new Exception("Unexpected value returned from getJniVersion(): 0x" + Integer.toHexString(res));
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8290482
* @summary Tests that DestroyJavaVM from an active thread fails.
* @run main/native TestActiveDestroy
*/
public class TestActiveDestroy {
static native boolean tryDestroyJavaVM();
static {
System.loadLibrary("activeDestroy");
}
public static void main(String[] args) throws Throwable {
if (tryDestroyJavaVM()) {
throw new Error("DestroyJavaVM succeeded when it should not!");
}
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <stdio.h>
#include <stdlib.h>
#include "jni.h"
static const char* jni_error_code(int ret) {
switch(ret) {
case JNI_OK: return "JNI_OK";
case JNI_ERR: return "JNI_ERR";
case JNI_EDETACHED: return "JNI_EDETACHED";
case JNI_EVERSION: return "JNI_EVERSION";
case JNI_ENOMEM: return "JNI_ENOMEM";
case JNI_EEXIST: return "JNI_EEXIST";
case JNI_EINVAL: return "JNI_EINVAL";
default: return "Invalid JNI error code";
}
}
JNIEXPORT jboolean JNICALL
Java_TestActiveDestroy_tryDestroyJavaVM(JNIEnv *env, jclass cls) {
JavaVM* jvm;
int res = (*env)->GetJavaVM(env, &jvm);
if (res != JNI_OK) {
fprintf(stderr, "GetJavaVM failed: %s\n", jni_error_code(res));
exit(1);
}
printf("Calling DestroyJavaVM from active thread\n");
res = (*jvm)->DestroyJavaVM(jvm);
printf("DestroyJavaVM returned: %s\n", jni_error_code(res));
return res == JNI_OK;
}