United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6507549 jvm crash while performing cursors finalizer
JDK-6507549 : jvm crash while performing cursors finalizer

Details
Type:
Bug
Submit Date:
2006-12-22
Status:
Closed
Updated Date:
2012-03-22
Project Name:
JDK
Resolved Date:
2011-03-07
Component:
client-libs
OS:
windows_vista,windows_xp
Sub-Component:
java.awt
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
6,6u3
Fixed Versions:

Related Reports
Backport:
Duplicate:
Duplicate:
Relates:
Relates:
Relates:

Sub Tasks

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
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.
                                     
2006-12-26
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;                
          }
                                     
2006-12-28
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.
                                     
2006-12-28
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.
                                     
2006-12-28



Hardware and Software, Engineered to Work Together