Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/hotspot/share/prims/jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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* );
Expand Down Expand Up @@ -3758,9 +3758,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));

Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/runtime/threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions src/java.base/share/native/include/jni.h
Original file line number Diff line number Diff line change
Expand Up @@ -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" */
Expand Down
4 changes: 2 additions & 2 deletions test/hotspot/jtreg/native_sanity/JniVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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!");
}
}
}
54 changes: 54 additions & 0 deletions test/hotspot/jtreg/runtime/jni/activeDestroy/libactiveDestroy.c
Original file line number Diff line number Diff line change
@@ -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;
}