Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#1112 Memory Leak in drawing rotated string

1.0.x
open
nobody
None
5
2 hours ago
2013-06-17
bcoun
No

I have created a live chart, that is updating 1000 times at a second, with six series in one chart. There I noticed a memory leak and started to search ... I found that this might be a problem in the JRE, but I could fix it through a simple change in the JFreeChart library. It is located in

org.jfree.text.TextUtilities.drawRotatedString(final String text, final Graphics2D g2, final float textX, final float textY, final double angle, final float rotateX, final float rotateY)

The problem seems to be, that if the string is drawed with an AttributedString or a TextLayout Object, the memory is leaking.

// Both options are leaking in JRE 7!!
if (useDrawRotatedStringWorkaround) {
        // workaround for JDC bug ID 4312117 and others...
        final TextLayout tl = new TextLayout(text, g2.getFont(),
            g2.getFontRenderContext());
        tl.draw(g2, textX, textY);
}
else {
    AttributedString as = new AttributedString(text,
        g2.getFont().getAttributes());
    g2.drawString(as.getIterator(), textX, textY);
}

You only see this in the process explorer, the heap stays constant. But after some time the program will be killed (Windows 7 64bit, JRE 7 32/64bit). So I changed the drawing to just draw the string to:

g2.drawString(text, textX, textY);

and it worked! There's no memory leaking anymore!

Here is an complete working example, where you can see the memory leaking:

final JFrame frm = new JFrame();
frm.getContentPane().setLayout(new BorderLayout());
frm.getContentPane().add(new JLabel() {
    @Override public void paint(Graphics g)
    {
        super.paint(g);
        Graphics2D gd = (Graphics2D) g;
        // Memory leaking:
        AttributedString as = new AttributedString("this is a memory leak", 
            gd.getFont().getAttributes());
        gd.drawString(as.getIterator(), 100, 100);
        // No memory leak:
        // gd.drawString("no memory leak here", 100, 100);
    }
}, BorderLayout.CENTER);
frm.setSize(500,350);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
new Thread() {
    @Override public void run() {
        while(true)
        {
            try
            {
                frm.getContentPane().repaint();
                Thread.sleep(1);
            } catch (InterruptedException ex)
            {
                ex.printStackTrace();
            }
        }
    }
}.start();

Discussion