JDK-6507549 : jvm crash while performing cursors finalizer
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6,6u3
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp,windows_vista
  • CPU: x86
  • Submitted: 2006-12-22
  • Updated: 2012-03-22
  • Resolved: 2011-03-07
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
6u4Fixed 7 b09Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
I have some frames( child ) which contains few AWT components & each components have set with different cursors. When frames are disposed &  all the components automatically disposed. Then i try to do some Garbage collection. When system tryies to do garbage collection jvm crashes. I have attached log files & testcase.
This happens only on windows platform. It works fine on 1.4.2 , 1.5.0 & 7.0 b04 . but failes in mustang 104 ( that i what i have). The crash does not happend every time , it happens once in every 4 to 5 times. 

Step to reproduce
---------------------
1) Run the attached program ( automated testcase). 
If you see jvm crash at the end of the testcase , then the bug it reproduce.

Comments
SUGGESTED FIX --- Cursor.java 2006-12-28 12:50:32.000000000 +0300 *************** *** 190,209 **** static class CursorDisposer implements sun.java2d.DisposerRecord { long pData; public void dispose() { ! finalizeImpl(pData); } } transient CursorDisposer disposer; private void setPData(long pData) { this.pData = pData; ! if (!GraphicsEnvironment.isHeadless() && pData != 0) { ! if (disposer == null) { ! // anchor is null after deserialization ! if (anchor == null) { ! anchor = new Object(); } - disposer = new CursorDisposer(); - sun.java2d.Disposer.addRecord(anchor, disposer); } disposer.pData = pData; } --- 190,213 ---- static class CursorDisposer implements sun.java2d.DisposerRecord { long pData; public void dispose() { ! if (pData != 0) { ! finalizeImpl(pData); ! } } } transient CursorDisposer disposer; private void setPData(long pData) { this.pData = pData; ! if (!GraphicsEnvironment.isHeadless()) { ! if (pData != 0) { ! if (disposer == null) { ! // anchor is null after deserialization ! if (anchor == null) { ! anchor = new Object(); ! } ! disposer = new CursorDisposer(); ! sun.java2d.Disposer.addRecord(anchor, disposer); } } disposer.pData = pData; }
28-12-2006

EVALUATION Here is what's going. The crash always happens on application shutdown, in particular when AWT toolkit is destroyed. In AwtToolkit::Dispose() we call AwtObjectList::Cleanup() which deletes all the AWT native objects including cursors. After this some of these cursors are finalized by Java2D Disposer. The code for this finalization is: static class CursorDisposer implements sun.java2d.DisposerRecord { long pData; public void dispose() { finalizeImpl(pData); } } 'finalizeImpl' is a native method that checks if pData is not null, converts it to 'AwtCursor *' and deletes. As the cursor has been already deleted, this leads to crash. The general problem is that AWT native objects may be deleted from two distinct places: from AwtToolkit disposal code and from Java2D Disposer. I'm not sure if any one of these places is enough, so I suggest to fix the problem another way. The only thing we need is to ensure that no AwtObject is deleted twice, from both places. This means: 1: If an object is deleted by Java2D Disposer, it shouldn't be deleted from AwtToolkit::Dispose() 2: If an object is deleted from AwtToolkit::Dispose(), it shouldn't be deleted by Java2D Disposer. 1 is now already true: when an object is being deleted, it is removed from the AwtObjectList, so it is not deleted in AwtToolkit::Dispose(). Thus, the only thing to fix is 2. As there is no way to remove the disposer record from Java2D Disposer, I suggest to set cursor disposer's pData to 0 when the corresponding record is deleted, and modify the code above to check if pData is not equal to 0. See suggested fix for details.
28-12-2006

EVALUATION I have also not found any place in JDK 7.0 code that fixes this problem. So the bug is not reproducible with 7.0 only due to some timings changed. The fix for 7.0 is right the same as for 6.0.
28-12-2006

EVALUATION The bug is reproducible with at least 6.0 and 6.0_01 and not reproducible with 7.0-b04. I suspect that the fix for 6387273 (integrated into 7.0-b02) has also eliminated this problem. However, we may want to fix this issue in some 6.0 update releases.
26-12-2006