Bug in JTextPane ??

Hi,

I am facing huge memory leak problems with JTextArea/JTextPane. After considerable investigation, I found out that the Document associated with the component is not being GC'ed properly. I ran OptimizeIt and found out that the memory is being consumed by the JTextPane.setText() method. I have implmented a HTML viewer to display large amounts of HTML data and it is leaking memory like crazy on each successive execution. Any thoughts ??

JDK1.4.2_01, WinXP

Here is the code fragment:

public class ReportViewer extends BaseFrame implements FontChange_int
{
      private      String            cReport;            
      private boolean            testMode = false;      

      // Graphical components
      private      BorderLayout      cMainLayout;
      private      JButton            cClose;
      private      JTextPane      cRptPane;
      private      Button            cClose2;

      private ViewUpdater     cViewUpdater = null;

      // Constants
      final      static      int      startupXSize = 650;
      final      static      int      startupYSize = 500;

      // Methods
      public ReportViewer(String report, ReportMain main)
      {
            // BaseFrame extends JFrame
            super("Reports Viewer", true, startupXSize, startupYSize);
            testMode     = false;
            cReport      = report;
            cViewUpdater = new ViewUpdater();
            initialize();
      }

      public void initialize()
      {
            // Create main layout manager
            cMainLayout = new BorderLayout();
            getContentPane().setLayout(cMainLayout);

            // Quick button bar - print, export, save as
            JToolBar      topPanel = new JToolBar();
            topPanel.setBorder(new BevelBorder(BevelBorder.RAISED) );
            java.net.URL      url;

            topPanel.add(Box.createHorizontalStrut(10));

            url = Scm.class.getResource("images/Exit.gif");
            cClose = new Button(new ImageIcon(url), true);
            cClose.setToolTipText("Close Window");
            topPanel.add(cClose);
            getContentPane().add(topPanel, BorderLayout.NORTH);

            // Main view window - HTML
            cRptPane = new JTextPane();
            cRptPane.setContentType("text/html");
            cRptPane.setEditable(false);

            JScrollPane sp = new JScrollPane(cRptPane);
            getContentPane().add(sp, BorderLayout.CENTER);

            // Main button - Close
            JPanel      bottomPanel = new JPanel();
            url = Scm.class.getResource("images/Exit.gif");
            cClose2 = new Button(new ImageIcon(url), "Close");
            bottomPanel.add(cClose2);
            getContentPane().add(bottomPanel, BorderLayout.SOUTH);

            cClose.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        closeWindow();
                  }
            });
            cClose2.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                        closeWindow();
                  }
            });

            show();
            cViewUpdater.setText(cReport);
            SwingUtilities.invokeLater(cViewUpdater);
      }


      protected void
      closeWindow()
      {
            super.closeWindow();

            // If I add the following lines, the GC reclaims
                // part of the memory but does not flush out the text
                // component as a whole
            
            /*Document doc = cRptPane.getDocument();
            try
            {
                  doc.remove(0,doc.getLength());
            }
            catch(Exception e) {;}
            doc=null; */
            
            cRptPane=null;
            cReport = null;
            cViewUpdater = null;
            dispose();
      }

      private class ViewUpdater implements Runnable
      {
            private String cText = null;

            public ViewUpdater() {;}

            public void
            setText(String text) {
                  cText = text;
            }
            
            public void
            run() {
                  cRptPane.setText(cText);
                  cRptPane.setCaretPosition(0);
                  cText = null;
            }
      }

      // Local main - for testing
      public static void main(String args[])
      {
            //new ReportViewer(str,comp);
      }
}


--
Sudarshan
www.spectrumscm.com

snraghavAsked:
Who is Participating?
 
savalouCommented:
The javadocs for JEditorPane (superclass of JTextPane) says:
"This is implemented to remove the contents of the current document, and replace them by parsing the given string using the current EditorKit. This gives the semantics of the superclass by not changing out the model, while supporting the content type currently set on this component. The assumption is that the previous content is relatively small, and that the previous content doesn't have side effects. Both of those assumptions can be violated and cause undesirable results. To avoid this, create a new document, getEditorKit().createDefaultDocument(), and replace the existing Document with the new one. You are then assured the previous Document won't have any lingering state. "

So it doesn't look like the Document object ever gets destroyed (WAD).  Can you try to implement the above suggestion?
0
 
TimYatesCommented:
> I ran OptimizeIt and found out that the memory is being consumed by the JTextPane.setText() method

Does the memory never get GCed?

How many references to this bit of memory does OptimizeIt say you have?

Do you run out of memory?
0
 
snraghavAuthor Commented:
Nope the memory never gets GCed and grows linearly on each successive execution. OptimizeIt reports that a large number of Object[] and ints are being created by the JTextPane.setText() method. More detailed investigation revealed that the objects are being created by the DefaultStyledDocument's ElementBuffer.insert() method. For some reason, the Document and its contents are sticky even if I null out all the references. I even tried trapping the Document events by writing my own listener and unregistering the listener upon close, but it doesn't seem to help.

--
Sudarshan
0
 
snraghavAuthor Commented:
savalou,

It is a decent workaround. I found out that this has been an open bug with Sun since 1999 !! The solution still leaks about 70kb for each successive execution (maybe the newly created document is sticky) but I can live with it. 70kb is much better than the 10 Mb I was previously leaking :-)

Thanks a ton ...

Sudarshan
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.