JDK-8167372 : Add code to check for getting oops while thread is in native
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-10-07
  • Updated: 2018-03-27
  • Resolved: 2017-12-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11
11 b01Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Relates :  
Description
Some recent errors in the code have gotten oops, while the thread_in_native which is essentially a naked oop.  Add a check to JNIHandles::make_global/local to make sure thread_in_vm.   See linked bug for details.
Comments
I've just noticed that this broke SPARC on old machines (see JDK-8200290).
27-03-2018

Potential fix for this issue once blocking bug JDK-8191227is fixed: diff --git a/src/hotspot/share/runtime/jniHandles.cpp b/src/hotspot/share/runtime/jniHandles.cpp --- a/src/hotspot/share/runtime/jniHandles.cpp +++ b/src/hotspot/share/runtime/jniHandles.cpp @@ -47,6 +47,7 @@ } else { Thread* thread = Thread::current(); assert(Universe::heap()->is_in_reserved(obj), "sanity check"); + assert(!current_thread_in_native(), "must not be in native"); return thread->active_handles()->allocate_handle(obj); } } @@ -59,6 +60,8 @@ return NULL; // ignore null handles } else { assert(Universe::heap()->is_in_reserved(obj), "sanity check"); + assert(thread->is_Java_thread(), "not a Java thread"); + assert(!current_thread_in_native(), "must not be in native"); return thread->active_handles()->allocate_handle(obj); } } @@ -70,6 +73,7 @@ } else { JavaThread* thread = JavaThread::thread_from_jni_environment(env); assert(Universe::heap()->is_in_reserved(obj), "sanity check"); + assert(!current_thread_in_native(), "must not be in native"); return thread->active_handles()->allocate_handle(obj); } } @@ -77,6 +81,7 @@ jobject JNIHandles::make_global(Handle obj) { assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); + assert(!current_thread_in_native(), "must not be in native"); jobject res = NULL; if (!obj.is_null()) { // ignore null handles @@ -93,6 +98,7 @@ jobject JNIHandles::make_weak_global(Handle obj) { assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); + assert(!current_thread_in_native(), "must not be in native"); jobject res = NULL; if (!obj.is_null()) { // ignore null handles @@ -265,6 +271,13 @@ weak_oops_do(&verify_handle); } +// This method is implemented here to avoid circular includes between +// jniHandles.hpp and thread.hpp. +bool JNIHandles::current_thread_in_native() { + Thread* thread = Thread::current(); + return (thread->is_Java_thread() && + JavaThread::current()->thread_state() == _thread_in_native); +} void jni_handles_init() { diff --git a/src/hotspot/share/runtime/jniHandles.hpp b/src/hotspot/share/runtime/jniHandles.hpp --- a/src/hotspot/share/runtime/jniHandles.hpp +++ b/src/hotspot/share/runtime/jniHandles.hpp @@ -48,6 +48,10 @@ template<bool external_guard> inline static oop resolve_impl(jobject handle); template<bool external_guard> static oop resolve_jweak(jweak handle); + // This method is not inlined in order to avoid circular includes between + // this header file and thread.hpp. + static bool current_thread_in_native(); + public: // Low tag bit in jobject used to distinguish a jweak. jweak is // type equivalent to jobject, but there are places where we need to @@ -231,6 +235,7 @@ template<bool external_guard> inline oop JNIHandles::resolve_impl(jobject handle) { assert(handle != NULL, "precondition"); + assert(!current_thread_in_native(), "must not be in native"); oop result; if (is_jweak(handle)) { // Unlikely result = resolve_jweak<external_guard>(handle);
28-11-2017

Proposed fix: diff --git a/src/share/vm/runtime/jniHandles.cpp b/src/share/vm/runtime/jniHandles.cpp --- a/src/share/vm/runtime/jniHandles.cpp +++ b/src/share/vm/runtime/jniHandles.cpp @@ -46,6 +46,7 @@ } else { Thread* thread = Thread::current(); assert(Universe::heap()->is_in_reserved(obj), "sanity check"); + assert(JavaThread::current()->thread_state() != _thread_in_native, "must not be in native"); return thread->active_handles()->allocate_handle(obj); } } @@ -58,6 +59,8 @@ return NULL; // ignore null handles } else { assert(Universe::heap()->is_in_reserved(obj), "sanity check"); + assert(thread->is_Java_thread(), "not a Java thread"); + assert(((JavaThread *)thread)->thread_state() != _thread_in_native, "must not be in native"); return thread->active_handles()->allocate_handle(obj); } } @@ -69,6 +72,7 @@ } else { JavaThread* thread = JavaThread::thread_from_jni_environment(env); assert(Universe::heap()->is_in_reserved(obj), "sanity check"); + assert(thread->thread_state() != _thread_in_native, "must not be in native"); return thread->active_handles()->allocate_handle(obj); } } @@ -76,6 +80,7 @@ jobject JNIHandles::make_global(Handle obj) { assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); + assert(JavaThread::current()->thread_state() != _thread_in_native, "must not be in native"); jobject res = NULL; if (!obj.is_null()) { // ignore null handles @@ -92,6 +97,7 @@ jobject JNIHandles::make_weak_global(Handle obj) { assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); + assert(JavaThread::current()->thread_state() != _thread_in_native, "must not be in native"); jobject res = NULL; if (!obj.is_null()) { // ignore null handles
01-06-2017