JDK-6471657 : JNI Direct Buffer API calls don't set the correct thread state during initialization
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-09-16
  • Updated: 2012-10-08
  • Resolved: 2006-11-14
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 6 JDK 7 Other
6u4Fixed 7Fixed hs10Fixed
Related Reports
Relates :  
Relates :  
Description
There is a general requirement that native methods calling in to the VM set the correct thread state when doing so - normally thread_in_vm. There is one path through the JNI direct buffer support initialization code that does not do this however. This leads to the thread being in state _thread_in_native instead of _thread_in_vm. A recent change to the os:sleep code (see CR 6459874) enabled a ThreadBlockInVM transition object that, in debug mode, enforces that the thread is in the state _thread_in_vm. As this is not the case then the assertion fails at runtime. Being in the wrong state is actually benign in terms of functionality. Further there has to be an initialization race between multiple threads for the os::sleep call to actually get executed.

Comments
SUGGESTED FIX *** /tmp/geta26218 Sat Sep 16 15:43:00 2006 --- jni.cpp Sat Sep 16 15:40:40 2006 *************** *** 2631,2637 **** JNI_END ! static bool initializeDirectBufferSupport(JNIEnv* env) { if (directBufferSupportInitializeFailed) { return false; } --- 2631,2637 ---- JNI_END ! static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) { if (directBufferSupportInitializeFailed) { return false; } *************** *** 2661,2666 **** --- 2661,2667 ---- directBufferSupportInitializeEnded = 1; } else { + ThreadInVMfromNative tivn(thread); // set state as yield_all can call os:sleep while (!directBufferSupportInitializeEnded && !directBufferSupportInitializeFailed) { os::yield_all(); } *************** *** 2678,2684 **** DTRACE_PROBE3(hotspot_jni, NewDirectByteBuffer__entry, env, address, capacity); if (!directBufferSupportInitializeEnded) { ! if (!initializeDirectBufferSupport(env)) { DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, NULL); return NULL; } --- 2679,2685 ---- DTRACE_PROBE3(hotspot_jni, NewDirectByteBuffer__entry, env, address, capacity); if (!directBufferSupportInitializeEnded) { ! if (!initializeDirectBufferSupport(env, thread)) { DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, NULL); return NULL; } *************** *** 2707,2713 **** DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret); if (!directBufferSupportInitializeEnded) { ! if (!initializeDirectBufferSupport(env)) { return 0; } } --- 2708,2714 ---- DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret); if (!directBufferSupportInitializeEnded) { ! if (!initializeDirectBufferSupport(env, thread)) { return 0; } } *************** *** 2733,2739 **** DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret); if (!directBufferSupportInitializeEnded) { ! if (!initializeDirectBufferSupport(env)) { ret = 0; return ret; } --- 2734,2740 ---- DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret); if (!directBufferSupportInitializeEnded) { ! if (!initializeDirectBufferSupport(env, thread)) { ret = 0; return ret; }
16-09-2006

EVALUATION The direct buffer initialization routine should set the correct thread state before calling the yield_all that leads to os:sleep.
16-09-2006