OPERATING SYSTEM: Solaris 10, AMD64 FULL JDK VERSION: Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_15-b04, mixed mode) DESCRIPTION from Licensee: We have encountered a situation where objects can go out of scope unexpectedly. In our case this leads to crash due a SIGSEGV in our JNI code, because a native structure is cleared away by finalisation before the native code has finished with it. Consider the following Java code: public void doStuff() { NativeThing nt = new NativeThing(); evaluateNativeThing(nt); } In our case, the constructor for NativeThing creates a new native structure, and stores a pointer to that structure in a long field. The evaluateNativeThing() method takes the pointer from the NativeThing instance's long field and passes it to some native code via JNI, which then does some work on the native structure. The NativeThing class implementation also contains a finalize() method to clear away the native structure associated with it prior to garbage collection. Occasionally, we see a SIGSEGV in the native evaluateNativeThing() code because the native stucture has been cleared away before we've finished with it. This should not be able to happen - the NativeThing instance should remain in scope until doStuff() returns. However, it seems that the NativeThing instance can actually go out of scope and be eligible for finalization before even the evaluateNativeThing() method has returned. We suspect that this is happening due to a Server JIT optimization based on the fact that the NativeThing instance *effectively* goes out of scope as soon as evaluateNativeThing() is called. This optimization would not cause a problem in pure Java code - the NativeThing instance in doStuff() is no longer required. However, in our case, the NativeThing instance passed to the implementation of evaluateNativeThing() points to the same native structure as the instance created in doStuff(), so when the instance in doStuff() is finalized, the instance in evaluateNativeThing() will point to a non-existent structure and we'll get a SIGSEGV when we attempt to dereference the pointer. We understand the need to optimize the code is ways such as this, and from a pure Java perspective the optimization is arguably a valid one. However, the optimization can clearly break code that is backed up by native structures via JNI. Moreover, the optimization conflicts with the JLS, which states: "The scope of a local variable declaration in a block is the rest of the block in which the declaration appears, starting with its own initializer" http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#103228 In the case we've highlighted here, the local variable "nt" clearly does NOT stay in scope for the whole of the block in which its declaration appears.
|