NOTICE! This is a static HTML version of a legacy ImageJ Trac ticket.

The ImageJ project now uses GitHub Issues for issue tracking.

Please file all new issues there.

Ticket #566 (closed defect: fixed)

Opened 2011-06-03T16:03:51-05:00

Last modified 2011-06-07T10:15:40-05:00

IJ2 Datasets are not always getting deleted

Reported by: bdezonia Owned by: bdezonia
Priority: major Milestone: biweekly-2011: Jun-06 to Jun-17
Component: Data Model Version:
Severity: serious Keywords:
Cc: Blocked By:
Blocking:

Description

Datasets do not seem to go away always. A scenario that shows this:

open sample clown
convert type to 12-bit unsigned
convert type back to Color RGB
close window
repeat

if you use debugger to inspect LegacyPlugin preharmonization() code you can see that old Datasets are sitting around with no associated ImagePlus and it recreates multiple data matching ImagePluses needlessly.

Is it possible that I need to worry about setTempCurrentImage() not getting undone after plugin run? Or some ImagePlus is sitting in LegacyMap that needs to be unregistered and since its not it maintains a link to a Dataset? Or somehow the deleted event is not propagating correctly.

Note - at some point I broke the 12-bit 3 channel Image getting converted back to an ImagePlus by the IJ1 plugin. So this bug may not be testable at the moment. Please leave open until Barry can recreate the bug or determine its fixed.

Change History

comment:1 Changed 2011-06-06T15:23:35-05:00 by bdezonia

Pinned down and worked with Curtis to find solution. Initial commit on b158e60b6f14f8355f755204274ed4f9beb56147.

Now there is an outstanding issue. Open Clown. Open Blobs. Close Clown. Exception thrown (see below). Can continually duplicate by alternating opening one and then deleting the other.

Exception: (related to ConcurrentModificationException in LegacyImageMap)

[WARN ] Exception thrown by;EventService subscriber:imagej.legacy.LegacyImageMap$1@1e9e5c73. Subscriber class:class imagej.legacy.LegacyImageMap$1
org.bushe.swing.exception.SwingException: Exception handling event topic event class=imagej.data.event.DatasetDeletedEvent, event=imagej.data.event.DatasetDeletedEvent@32fbca58, topic=null, eventObj=null
org.bushe.swing.exception.SwingException: Exception handling event topic event class=imagej.data.event.DatasetDeletedEvent, event=imagej.data.event.DatasetDeletedEvent@32fbca58, topic=null, eventObj=null

at org.bushe.swing.event.ThreadSafeEventService.handleException(ThreadSafeEventService.java:2021)
at org.bushe.swing.event.ThreadSafeEventService.handleException(ThreadSafeEventService.java:2009)
at org.bushe.swing.event.ThreadSafeEventService.publish(ThreadSafeEventService.java:975)
at org.bushe.swing.event.SwingEventService.publish(SwingEventService.java:78)
at org.bushe.swing.event.ThreadSafeEventService.publish(ThreadSafeEventService.java:904)
at org.bushe.swing.event.EventBus.publish(EventBus.java:57)
at imagej.event.Events.publish(Events.java:52)
at imagej.data.Dataset.delete(Dataset.java:329)
at imagej.data.AbstractDataObject.decrementReferences(AbstractDataObject.java:72)
at imagej.display.AbstractDisplayView.dispose(AbstractDisplayView.java:115)
at imagej.ui.swing.display.SwingImageDisplay$1.windowClosed(SwingImageDisplay.java:102)
at java.awt.AWTEventMulticaster.windowClosed(AWTEventMulticaster.java:343)
at java.awt.AWTEventMulticaster.windowClosed(AWTEventMulticaster.java:342)
at java.awt.Window.processWindowEvent(Window.java:1868)
at javax.swing.JFrame.processWindowEvent(JFrame.java:274)
at java.awt.Window.processEvent(Window.java:1823)
at java.awt.Component.dispatchEventImpl(Component.java:4736)
at java.awt.Container.dispatchEventImpl(Container.java:2143)
at java.awt.Window.dispatchEventImpl(Window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4566)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:680)
at java.awt.EventQueue.access$000(EventQueue.java:86)
at java.awt.EventQueue$1.run(EventQueue.java:639)
at java.awt.EventQueue$1.run(EventQueue.java:637)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
at java.awt.EventQueue$2.run(EventQueue.java:653)
at java.awt.EventQueue$2.run(EventQueue.java:651)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:650)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Caused by: java.util.ConcurrentModificationException

at java.util.WeakHashMap$HashIterator.nextEntry(WeakHashMap.java:762)
at java.util.WeakHashMap$KeyIterator.next(WeakHashMap.java:795)
at imagej.legacy.LegacyImageMap.unregisterDataset(LegacyImageMap.java:135)
at imagej.legacy.LegacyImageMap$1.onEvent(LegacyImageMap.java:157)
at imagej.legacy.LegacyImageMap$1.onEvent(LegacyImageMap.java:1)
at org.bushe.swing.event.ThreadSafeEventService.publish(ThreadSafeEventService.java:971)
... 35 more

comment:2 Changed 2011-06-06T15:26:43-05:00 by bdezonia

Made all access to the imageMap within LegacyImageMap synchronized. This did not fix the issue.

comment:3 Changed 2011-06-07T09:54:49-05:00 by bdezonia

Fixed in b4dc108f515eab63c9d1a911d44f4bc23117b91c. Using ConcurrentHashMap instead of WeakHashMap. Also specifically telling IJ1 to throw away ImagePluses when their Datasets have been deleted.

There is some question as to whether Datasets not associated with Displays are being left around and have IJ1 resources tied to them. Somewhere we may need to go through the LegacyImageMap calling unregisterDataset() over and over. Must think where this makes sense to do.

comment:4 Changed 2011-06-07T10:15:40-05:00 by bdezonia

  • Status changed from new to closed
  • Resolution set to fixed

Inspection seems to show that Datasets only register with the ObjectManager when they are tied to a Display. Only those displayed Datasets are ever translated to ImagePluses and sent to IJ1. Thus as they themselves become irrelevant they free up IJ1 ImagePluses too. There is no case where undisplayed Datasets are getting ImagePluss associated with them that never get released.