JDK-4976333 : Same jni code causes jvm to crash after upgrading from 141 to 142_03
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.4.2_03
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • OS:
    linux_redhat_2.1,solaris_8,windows_2000 linux_redhat_2.1,solaris_8,windows_2000
  • CPU: x86,sparc
  • Submitted: 2004-01-09
  • Updated: 2012-10-08
  • Resolved: 2004-03-30
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.
Other
1.4.2_05 05Fixed
Description
My ISV is experiencing JNI problem - JVM crash with signal SIGABRT - after
upgrading from jre141_03 to jre142_03 with no code changes. Currently I don't have a testcase, but please look at the following pseudo code and shed some light on the questions. Your help is highly appreciated. BTW, the problem happens on multiple platforms: Solaris8, Windows2000, and RHAS2.1.

Basically, the overall architecture is:


UQSRV(c++) <-> JavaMessageServer(java) <-> dispatcher(c++)


In the above diagram, UQSRV is a server process written in c++. When a message event comes in, UQSRV passes the event to JavaMessageServer through JNI invocation(i.e. JNI_CreateJavaVM). JavaMessageServer then creates a java object KNEvent(pure java). After that, it calls dispatcher(native method defined in JavaMessageServer and implemented in c++) to dispatch it. The pseudo code is:

// create jvm instance in UQSRV through invocation
// vm flags are -verbose:jni -Xcheck:jni and the flags are for debug purpose
// vm will crash even without these flags
//

...
JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);
...

// then eventually it goes to dispatch native method 
void dispatch(JNIEnv *env, jobject object) {
  // get a globalref of object
  gJObject=env->NewGlobalRef(object);
  // delete the old one
  env->DeleteLocalRef(object);
}


In jre141, the same code runs fine; while in jre142, it's dumping core and the core file shows jvm is crashing at env->DeleteLocalRef() in method dispatch.
Error message from -verbose:jni -Xcheck:jni seems to confirm that:


FATAL ERROR in native method: Invalid local JNI handle passed to
DeleteLocalRef


Therefore, the ISV has the following questions/comments:
1. Is the above code correct? In JNI spec1.1, DeleteLocalRef() is applicable to local reference and passed-in argument seems to be viewed as local reference too(pass by reference for java object). So, could someone confirm that DeleteLocalRef() can be applied to a passed in java object?

2. If DeleteLocalRef() cannot be applied to passed-in java object(such as a spec change between minor releases?), why jre141 runs fine? 

3. If DeleteLocalRef() can be applied to passed-in java object as in jre141, it then is a bug(or regression) in jre142.

4. To further confirm the problem is from DeleteLocalRef(), I comment out the line which has DeleteLocalRef() and everything works fine afterwards. To use it as a workaround, the ISV would like to know whether commenting out DeleteLocalRef() will introduce memory leak. 

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.4.2_05 generic tiger-beta2 FIXED IN: 1.4.2_05 tiger-beta2 INTEGRATED IN: 1.4.2_05 tiger-b51
14-06-2004

WORK AROUND Commenting out env->DeleteLocalRef is NOT acceptable for the ISV, not only because it has not been stree tested, but also because it involves huge patch update work.
11-06-2004

SUGGESTED FIX ------- jniCheck.cpp ------- *** /tmp/sccs.msaiOo Thu Jan 15 14:56:37 2004 --- jniCheck.cpp Tue Jan 13 16:37:12 2004 *************** *** 563,569 **** functionEnter(thr); IN_VM( ValidateObject(thr, obj); ! if (obj && !JNIHandles::is_local_handle(thr, obj)) ReportJNIFatalError(thr, "Invalid local JNI handle passed to DeleteLocalRef"); ) --- 563,569 ---- functionEnter(thr); IN_VM( ValidateObject(thr, obj); ! if (obj && !(JNIHandles::is_local_handle(thr, obj) || is_frame_handle(thr, obj))) ReportJNIFatalError(thr, "Invalid local JNI handle passed to DeleteLocalRef"); ) ###@###.### 2004-01-15
15-01-2004

EVALUATION After further investigation, the customer actually put the check:jni flag in their native code. After remove the flag, the application does not crash. So the crash only happens with the fatalerror code in check:jni. The fatalerror code reached because that in check deleteLocalRef(), it does not check if the local handle is frame handle after 1.4.2. I think it is probably intentionally removed because deleteLocalRef() for frame handle is not needed. ###@###.### 2004-01-13
13-01-2004