Menu

#1112 Memory Leak in drawing rotated string

1.0.x
closed
None
5
2017-02-09
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

  • David Gilbert

    David Gilbert - 2017-02-09
    • status: open --> closed
    • assigned_to: David Gilbert
     
  • David Gilbert

    David Gilbert - 2017-02-09

    Thanks for the feedback. I guess you reported this to Oracle as well as I see it was fixed in Java 8:

    http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8017146

    Best regards,
    David

     

Log in to post a comment.