JDK-6919629 : Nimbus L&F Nimbus.Overrides option leaks significant amounts of memory
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6u18
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2010-01-25
  • Updated: 2011-03-07
  • Resolved: 2011-03-07
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.
JDK 7 Other
7 b94Fixed OpenJDK6Fixed
Description
FULL PRODUCT VERSION :
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) Server VM (build 16.0-b13, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux localhost.localdomain 2.6.31.5-127.fc12.i686.PAE #1 SMP Sat Nov 7 21:25:57 EST 2009 i686 i686 i386 GNU/Linux

Windows XP SP 3

A DESCRIPTION OF THE PROBLEM :

If you create/destroy swing components which have defined the Nimbus.Overrides client properrty - Nimbus leaks substantial number of the following objects:

com.sun.java.swing.plaf.nimbus.NimbusDefaults$ColorTree$Node
java.util.LinkedList$Entry
java.util.LinkedList
com.sun.java.swing.plaf.nimbus.DerivedColor$UIResource
(approx 30,000 objects each - representing about 100 create/destroy cycles)

Other objects leak as well - but not to same extent as above.

sun.awt.image.BufImgSurfaceData
java.lang.Integer
java.awt.Font
java.awt.image.BufferedImage
java.awt.geom.Rectangle2D$Float
sun.awt.image.IntegerInterleavedRaster
java.lang.Object
java.awt.image.DataBufferInt
java.awt.Color
sun.awt.image.BufImgVolatileSurfaceManager
(approx 100 objects each - representing about 100 create/destroy cycles)

On an WinXP machine delibretely limited to only 64M of Heap (represents minimum spec machine) - the rich client application I have grinds to a halt after about 100 screen entries. Typical user will get there in less than 20 minutes.

I also have some .png files grabbed from doing filter based on least squares fit for jmap -histo:live dumps run every second. On version 18 it is quite clear that there is a substantial memory leak. On version 10 no such leak is present.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See source code example below.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No memory leak.
ACTUAL -
A memory leak.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

Following code segment replicates the defect:

import java.awt.Insets;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;


public class NimbusBug
{
    public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, InterruptedException
    {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
    
        JFrame frame =new JFrame();
        UIDefaults nimbus=new UIDefaults();
        nimbus.put("Button.contentMargins",new Insets(6,0,6,0));
        
        while ( true ) {
            JDialog dialog = new JDialog(frame,"Test");
            JButton button  =new JButton("Hello World");
            button.putClientProperty("Nimbus.Overrides",nimbus);
            dialog.getContentPane().add(button);
            
            dialog.pack();
            dialog.setVisible(true);
            
            Thread.sleep(100);
            dialog.setVisible(false);
            dialog.dispose();
            
            Thread.sleep(1000);
         }
    }
}



---------- END SOURCE ----------

Comments
EVALUATION Nimbus keeps a cache of custom styles, i.e. for each component that has overrides its style is stored. This cache is a WeakHashMap, so its keys are weak, but the values (of type NimbusStyle) keep a strong reference to the component. So once a component has overrides, it ends up in the cache and is never released from it. To fix this, i suggest NimbusStyle keep a weak reference to its component.
29-04-2010