-
Bug
-
Resolution: Fixed
-
P3
-
6, 7, 8, 11, 12
-
b03
-
x86
-
windows_xp
FULL PRODUCT VERSION :
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)
java version "1.6.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-rc-b71)
Java HotSpot(TM) Client VM (build 1.6.0-rc-b71, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
When adding a component to a JTabbedPane, a JTabbedPane$Page object is instantiated. If the JTabbedPane has an AccessibleContext and the Component to add is Accessible, component.getAccessibleContext().setParent(page) is performed during the Page construction (in initAccessibleContext()).
When removing the component from the JTabbedPane, its accessibleContext's accessibleParent is not cleared, leaving a reference to the JTabbedPane$Page (and thus the JTabbedPane) hanging around. This can cause memory leaks that are quite difficult to track down.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
As performed in the included test case:
- Add a component to a JTabbedPane. The JTabbedPane must have an AccessibleContext.
- Remove the component from the JTabbedPane (with one of remove(), removeTabAt(), removeAll(), etc.).
- Note that the component still holds a reference to an inner class (Page) of JTabbedPane as its accessibleContext's accessibleParent.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Once removed from a JTabbedPane, a component retains no references to the JTabbedPane or its inner classes.
ACTUAL -
Once removed from a JTabbedPane, a component keeps a reference to an instance of the inner class Page of the JTabbedPane, preventing the Page (and therefore the JTabbedPane, its parent, etc.) from being garbage collected.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.*;
public class TabbedPaneMemLeak
{
public static void main(String[] args)
{
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.getAccessibleContext(); // Ensure that the JTabbedPane has an AccessibleContext
JComponent component = new JPanel();
System.out.println(component.getAccessibleContext().getAccessibleParent()); // null
tabbedPane.addTab("Component", component);
System.out.println(component.getAccessibleContext().getAccessibleParent()); // JTabbedPane$Page
tabbedPane.removeAll(); // Could also be tabbedPane.remove(component) or tabbedPane.removeTabAt(0)
// WORKAROUND: component.getAccessibleContext().setAccessibleParent(null);
System.out.println(component.getAccessibleContext().getAccessibleParent()); // BUG: JTabbedPane$Page (should be null)
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Manually perform getAccessibleContext().setAccessibleParent(null) on components removed from a JTabbedPane.
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)
java version "1.6.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-rc-b71)
Java HotSpot(TM) Client VM (build 1.6.0-rc-b71, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
When adding a component to a JTabbedPane, a JTabbedPane$Page object is instantiated. If the JTabbedPane has an AccessibleContext and the Component to add is Accessible, component.getAccessibleContext().setParent(page) is performed during the Page construction (in initAccessibleContext()).
When removing the component from the JTabbedPane, its accessibleContext's accessibleParent is not cleared, leaving a reference to the JTabbedPane$Page (and thus the JTabbedPane) hanging around. This can cause memory leaks that are quite difficult to track down.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
As performed in the included test case:
- Add a component to a JTabbedPane. The JTabbedPane must have an AccessibleContext.
- Remove the component from the JTabbedPane (with one of remove(), removeTabAt(), removeAll(), etc.).
- Note that the component still holds a reference to an inner class (Page) of JTabbedPane as its accessibleContext's accessibleParent.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Once removed from a JTabbedPane, a component retains no references to the JTabbedPane or its inner classes.
ACTUAL -
Once removed from a JTabbedPane, a component keeps a reference to an instance of the inner class Page of the JTabbedPane, preventing the Page (and therefore the JTabbedPane, its parent, etc.) from being garbage collected.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.*;
public class TabbedPaneMemLeak
{
public static void main(String[] args)
{
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.getAccessibleContext(); // Ensure that the JTabbedPane has an AccessibleContext
JComponent component = new JPanel();
System.out.println(component.getAccessibleContext().getAccessibleParent()); // null
tabbedPane.addTab("Component", component);
System.out.println(component.getAccessibleContext().getAccessibleParent()); // JTabbedPane$Page
tabbedPane.removeAll(); // Could also be tabbedPane.remove(component) or tabbedPane.removeTabAt(0)
// WORKAROUND: component.getAccessibleContext().setAccessibleParent(null);
System.out.println(component.getAccessibleContext().getAccessibleParent()); // BUG: JTabbedPane$Page (should be null)
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Manually perform getAccessibleContext().setAccessibleParent(null) on components removed from a JTabbedPane.
- relates to
-
JDK-8066493 [macosx] Tab group has null children
- Open