Solved

Bug in JTextPane ??

Posted on 2003-10-28
4
906 Views
Last Modified: 2008-02-01
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

0
Comment
Question by:snraghav
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 35

Expert Comment

by:TimYates
ID: 9634676
> 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
 

Author Comment

by:snraghav
ID: 9635563
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
 
LVL 3

Accepted Solution

by:
savalou earned 50 total points
ID: 9637268
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
 

Author Comment

by:snraghav
ID: 9637656
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

Featured Post

Salesforce Has Never Been Easier

Improve and reinforce salesforce training & adoption using WalkMe's digital adoption platform. Start saving on costly employee training by creating fast intuitive Walk-Thrus for Salesforce. Claim your Free Account Now

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
This video teaches viewers about errors in exception handling.

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question