JDK-4768127 : ToolTipManager not removed from components
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.1
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-10-24
  • Updated: 2002-11-16
  • Resolved: 2002-11-16
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
1.4.2 mantisFixed
Related Reports
Relates :  
Relates :  
Description
In certain situation, ToolTipManager does not remove itself from component, registered as MouseMotionListener. The result is that more and more ToolTipManagers are registered on components, leaking memory and gradually downgrading performance. Reproduced on j2se 1.4.0 and 1.4.1, Windows 2000.

This problem appears when a window with affected component (tested with JTree) is not focused and user clicks on it. On mousePressed, ToolTipManager sets 'insideComponent' to null, so it does not know the component on which it is registered. And it is registered at the moment - it happened on mouseEntered - when user moved cursor over the component (before click). With mouse button release following immediately, mouseExited and mouseEntered events are generated. Now, ToolTipManager can't remove itself on mouseExited as normally because 'insideComponent' is null, but it adds itself again on mouseEntered.

This can be simply reproduced e.g. on two JTree components with tooltips placed in two JInternalFrame windows, then clicking between them (click on the JTrees). With each click there's one more ToolTipManager as MouseMotionListener added to JTree. You may try the following code, or attached zip file containg also hacked JDK classes printing some debug messages.

public class ToolTipManagerLeak extends javax.swing.JFrame {
    
    public ToolTipManagerLeak() {
        jDesktopPane1 = new javax.swing.JDesktopPane();
        jInternalFrame1 = new javax.swing.JInternalFrame();
        jTree1 = new javax.swing.JTree();
        jInternalFrame2 = new javax.swing.JInternalFrame();
        jTree2 = new javax.swing.JTree();

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });

        jInternalFrame1.setVisible(true);
        jTree1.setToolTipText("1");
        jInternalFrame1.getContentPane().add(jTree1, java.awt.BorderLayout.CENTER);

        jInternalFrame1.setBounds(20, 20, 130, 160);
        jDesktopPane1.add(jInternalFrame1, javax.swing.JLayeredPane.DEFAULT_LAYER);

        jInternalFrame2.setVisible(true);
        jTree2.setToolTipText("2");
        jInternalFrame2.getContentPane().add(jTree2, java.awt.BorderLayout.CENTER);

        jInternalFrame2.setBounds(210, 20, 130, 220);
        jDesktopPane1.add(jInternalFrame2, javax.swing.JLayeredPane.DEFAULT_LAYER);

        getContentPane().add(jDesktopPane1, java.awt.BorderLayout.CENTER);

        pack();
        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setSize(new java.awt.Dimension(400, 300));
        setLocation((screenSize.width-400)/2,(screenSize.height-300)/2);
    }
    
    private void exitForm(java.awt.event.WindowEvent evt) {
        System.exit(0);
    }
    
    public static void main(String args[]) {
        new ToolTipManagerLeak().show();
    }
    
    
    private javax.swing.JInternalFrame jInternalFrame2;
    private javax.swing.JTree jTree2;
    private javax.swing.JInternalFrame jInternalFrame1;
    private javax.swing.JDesktopPane jDesktopPane1;
    private javax.swing.JTree jTree1;
}

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis FIXED IN: mantis INTEGRATED IN: mantis mantis-b08
24-08-2004

EVALUATION xxx Name: apR10133 Date: 10/26/2002 The problem is that component inside internal frame can handle some mouse events twice. If mouse enter to the inactive internal frame its glassPane retargets mouse events to the appropriate component in frame. Then if we click mouse over the internal frame its glassPane becomes not visible and mouse really enter the same component which already handled MOUSE_ENTERED event (retargeted from glassPane). At the same time mousePressed method of ToolTipManager resets the insideComponent to null. After that mouseExited can't remove mouse motion listener from the component it was added. So the mouse motion listener are added two times and then removed once. ###@###.### ======================================================================
24-08-2004

SUGGESTED FIX Name: apR10133 Date: 10/26/2002 ------- ToolTipManager.java ------- *** /tmp/sccs.Caa4DM Fri Oct 25 20:21:33 2002 --- ToolTipManager.java Fri Oct 25 20:18:43 2002 *************** *** 479,484 **** --- 479,485 ---- if (insideComponent != null) { enterTimer.stop(); } + component.removeMouseMotionListener(this); component.addMouseMotionListener(this); boolean sameComponent = (insideComponent == component); ###@###.### ======================================================================
24-08-2004