JDK-8040248 : Drag and drop between two components fails if performed quickly
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7u51,8,9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: linux
  • CPU: generic
  • Submitted: 2014-04-15
  • Updated: 2018-09-05
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
tbdUnresolved
Related Reports
Relates :  
Description
Assume user attemps a drag-and-drop operation between two components inside one JRE. So DataFlavor.javaJVMLocalObjectMimeType is used, and the transferable is local to the JVM.

In such case the transferable is stored to a static variable in SunDropTargetContextPeer.setCurrentJVMLocalSourceTransferable(). When processEnterMessage() is handled, its value is copied to instance variable "local". The instance variable is cleaned by processExitMessage(), the static variable is cleared by SunDragSourceContextPeer.cleanup().

If drag-and-drop operation is performed quickly, SunDragSourceContextPeer.cleanup() is called when mouse button is released and *before* processEnterMessage() is called. So when EDT finally handles MOUSE_ENTERED event and DropTargetListener.dragEnter() gets called, "local" transferable is already null. The listener tries to get the data from the transferable:
DropTargetDragEvent.getTransferable(), and then
Transferable.getTransferData(dataFlavor).

The dataFlavor has MIME type of DataFlavor.javaJVMLocalObjectMimeType, and SunDropTargetContextPeer.currentJVMLocalSourceTransferable is already cleared. The representationClass field of the DataFlavor object is set to java.io.InputStream.class. So when SunDropTargetContextPeer.getNativeData() executes it tries to cast the data object to java.io.InputStream to deserialize the data but fails with the exception:
java.lang.ClassCastException: JDK8024061$DropObject cannot be cast to java.io.InputStream
	at sun.awt.datatransfer.DataTransferer.translateTransferable(DataTransferer.java:1368)
	at sun.awt.datatransfer.DataTransferer$6.run(DataTransferer.java:2323)
	at sun.awt.datatransfer.DataTransferer.processDataConversionRequests(DataTransferer.java:2380)
	at sun.awt.X11.XSelection.waitForSelectionNotify(XSelection.java:179)
	at sun.awt.X11.XSelection.getData(XSelection.java:295)
	at sun.awt.X11.XDnDDropTargetProtocol.getData(XDnDDropTargetProtocol.java:859)
	at sun.awt.X11.XDropTargetContextPeer.getNativeData(XDropTargetContextPeer.java:151)
	at sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:263)
	at sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:73)
	at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:376)
	at JDK8024061$DnDPanel$3.dragEnter(JDK8024061.java:200)
	at java.awt.dnd.DropTarget.dragEnter(DropTarget.java:357)
	at sun.awt.dnd.SunDropTargetContextPeer.processEnterMessage(SunDropTargetContextPeer.java:330)
	at sun.awt.X11.XDropTargetContextPeer.processEnterMessage(XDropTargetContextPeer.java:165)
	at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEnterEvent(SunDropTargetContextPeer.java:798)
	at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(SunDropTargetContextPeer.java:766)
	at sun.awt.dnd.SunDropTargetEvent.dispatch(SunDropTargetEvent.java:48)
	at java.awt.Component.dispatchEventImpl(Component.java:4716)
	at java.awt.Container.dispatchEventImpl(Container.java:2287)
	at java.awt.Component.dispatchEvent(Component.java:4687)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
	at java.awt.LightweightDispatcher.trackMouseEnterExit(Container.java:4620)
	at java.awt.LightweightDispatcher.processDropTargetEvent(Container.java:4558)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4417)
	at java.awt.Container.dispatchEventImpl(Container.java:2273)
	at java.awt.Window.dispatchEventImpl(Window.java:2719)
	at java.awt.Component.dispatchEvent(Component.java:4687)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
	at java.awt.EventQueue.access$200(EventQueue.java:103)
	at java.awt.EventQueue$3.run(EventQueue.java:694)
	at java.awt.EventQueue$3.run(EventQueue.java:692)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
	at java.awt.EventQueue$4.run(EventQueue.java:708)
	at java.awt.EventQueue$4.run(EventQueue.java:706)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

This exception is caught internally, and IOException is thrown as it failed to get the data:
java.io.IOException: Owner failed to convert data
	at sun.awt.X11.XSelection.validateDataGetter(XSelection.java:444)
	at sun.awt.X11.XSelection.getData(XSelection.java:305)
	at sun.awt.X11.XDnDDropTargetProtocol.getData(XDnDDropTargetProtocol.java:859)
	at sun.awt.X11.XDropTargetContextPeer.getNativeData(XDropTargetContextPeer.java:151)
	at sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:263)
	at sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:73)
	at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:376)
	at JDK8024061$DnDPanel$3.dragEnter(JDK8024061.java:200)
	at java.awt.dnd.DropTarget.dragEnter(DropTarget.java:357)
	at sun.awt.dnd.SunDropTargetContextPeer.processEnterMessage(SunDropTargetContextPeer.java:330)
	at sun.awt.X11.XDropTargetContextPeer.processEnterMessage(XDropTargetContextPeer.java:165)
	at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEnterEvent(SunDropTargetContextPeer.java:798)
	at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(SunDropTargetContextPeer.java:766)


At the same time, no IO should have occurred because a local source was dragged, so this exception is rather unexpected.


What actually happens is that native drag-and-drop operation completed already whereas this drag-and-drop operation on EDT didn't even started yet.
Comments
Stand-alone application to reproduce the issue.
15-04-2014

If DataFlavor is constructed with "class" parameter: new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + DropObject.class.getName()); instead of simply new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType); then the following exception is thrown: java.awt.datatransfer.UnsupportedFlavorException: application/x-java-jvm-local-objectref at sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:254) at sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:73) at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:376) at JDK8024061$DnDPanel$3.dragEnter(JDK8024061.java:199) at java.awt.dnd.DropTarget.dragEnter(DropTarget.java:357) at sun.awt.dnd.SunDropTargetContextPeer.processEnterMessage(SunDropTargetContextPeer.java:330) at sun.awt.X11.XDropTargetContextPeer.processEnterMessage(XDropTargetContextPeer.java:165) ���
15-04-2014