JDK-6219874 : JNI document should say to invoke "DetachCurrentThread()" on thread exit
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.4.2,1.4.2_06
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_8
  • CPU: sparc
  • Submitted: 2005-01-21
  • Updated: 2017-05-16
  • Resolved: 2005-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 6
6 betaFixed
Related Reports
Relates :  
Description
JVM crashes in an application using JNI feature.

CONFIGURATION :
   JRE/JDK : 1.3.1_11/1.4.2_06
   OS : Solaris 8(T2) and Solaris 9

REPRODUCE :
  1) Compile the attached X.java in 1.4.2_06

---- X.java --->
class X
{
  static {
    System.loadLibrary("X");
  }
  static native void xxx();
  public static void  main(String[] arg) throws Exception
  {
    for (int i = 0 ; i < 10 ; ++i) {
      xxx();
      Thread.sleep(1000);
    }
  }
}
<---


  2) Compile the attached x.c 

--- x.c --->
#include <jni.h>
#include <thread.h>

static JavaVM *jvm = NULL;

static void *zzz(void *arg)
{
  int n;
  JNIEnv *env;

  printf("zzz  %x\n", &n);
  (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
  /*  (*jvm)->DetachCurrentThread(jvm);  */
}

/*
 * Class:     X
 * Method:    xxx
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_X_xxx(JNIEnv *env, jclass klass)
{
  thread_t tid;

  if (NULL == jvm)
    (*env)->GetJavaVM(env, &jvm);

  thr_create(0, 0, zzz, 0, 0, &tid);
}
<---
       ex. 
         cc -G -I/java/jdk1.4.2_06/solaris/include -I/java/jdk1.4.2_06/solaris/include/solaris x.c -o libX.so

  3) Launch 
        "env LD_LIBRARY_PATH=/usr/lib/lwp:. ; java X"

  The follwoing message will show up.
---->
% env LD_LIBRARY_PATH=/usr/lib/lwp:. ; java X
zzz  f1efbf98
zzz  f1efbf98
#
# HotSpot Virtual Machine Error, Internal Error
# Please report this error at
# http://java.sun.com/cgi-bin/bugreport.cgi
#
# Java VM: Java HotSpot(TM) Client VM (1.4.2_06-b03 mixed mode)
#
# Error ID: 5448524541442C4F43414C33544F524147450E4350500058 01
#
# Problematic Thread: prio=16777216 tid=0x000ec390 nid=0x9 runnable
#

Heap at VM Abort:
Heap
 def new generation   total 2112K, used 121K [0xf2000000, 0xf2220000, 0xf2710000
)
  eden space 2048K,   5% used [0xf2000000, 0xf201e580, 0xf2200000)
  from space 64K,   0% used [0xf2200000, 0xf2200000, 0xf2210000)
  to   space 64K,   0% used [0xf2210000, 0xf2210000, 0xf2220000)
 tenured generation   total 1408K, used 0K [0xf2710000, 0xf2870000, 0xf6000000)
   the space 1408K,   0% used [0xf2710000, 0xf2710000, 0xf2710200, 0xf2870000)
 compacting perm gen  total 4096K, used 966K [0xf6000000, 0xf6400000, 0xfa000000
)
   the space 4096K,  23% used [0xf6000000, 0xf60f1b00, 0xf60f1c00, 0xf6400000)
Abort
% 
<---

WORKAROUND :
    To invoke DetachCurrentThread() on thread exit
    (Please see the line commended out in the test case.)

REQUEST : 
    To mention explicitly "JNI user should invoke DetachCurrentThread() on thread exit"
     in JNI document.
   


REPORT(1.4.2_06) : 
   The program terminates at
       guarantee(get_thread()      == thread, "must be the same thread, quickly");
   in  ThreadLocalStorage::set_thread.
   get_thread_via_cache_slowly which is called in  get_thread  sets cache.
   Stack pointer is used as cache entry key.
   
   According to the message which the test program outputs,
   When runtime uses T2 lib, there seems the case which the stack area , which was used 
   by exited thread come to be used by another thread. The cache system does not seem to 
   work well.
   This is because stack pointer is used as cache entry key.

   Actually, the test program works well in 5.0fcs. In 5.0fcs, thread ID is used 
   as cache entry key.
   So, the abnormal termination does not occur.


###@###.### 2005-1-21 00:50:11 GMT

Comments
EVALUATION JNI spec was updated as suggested.
15-12-2005

EVALUATION The document should indicate jni_DetachCurrentThread is mondatory since if not called, the JavaThread will not be cleared and removed from Thread list. More important the cache will be cleared. There will be some memory leak without calling the function too. The senario in this test case without Detach: thread 1 created, executes xxx, attached to JavaThread, note a JavaThread will be creadted, because get_thread_slow will get a NULL back. Afer new JavaThread created and initialized, the cache will contains "this" threadi(JavaThread will run too, set the cache slot) . Then thread 1 exit, lead to a JavaThread remains in Thread list. thread 2 created, executes xxx, reuse the stack region by thread 1 (why not? OS will manage to do this), attach to a JavaThread, same as above, a new JavaThread will be created since under this thread context, thread_get_slow will return NULL. the JavaThread will be init'ed too, and put into Thread local Storage. At the initialization stage, the corresponding cache slot (to this thread) already store a JavaThread of 1, so the guarantee failed. 1.5 overwrite the slot in init stage, so it will not crash. While jni_DetachCurrentThread called, the cache slot will be reset, so there is no cache hit, will get from slow path. This is not a bug, customer should pay attention to the usage of attaching threads. ###@###.### 2005-05-25 21:39:47 GMT reassign to PDE for further proposal. ###@###.### 2005-06-28 19:58:04 GMT
21-01-2005