Solved

Bug in JTextPane ??

Posted on 2003-10-28
4
898 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
  • 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

ScreenConnect 6.0 Free Trial

At ScreenConnect, partner feedback doesn't fall on deaf ears. We collected partner suggestions off of their virtual wish list and transformed them into one game-changing release: ScreenConnect 6.0. Explore all of the extras and enhancements for yourself!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
fibonacci ten numbers 4 39
Tomcat: Unable to run tomcat service. 2 20
Unhandled exception type Exception 18 31
What's wrong with this code? 4 23
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

803 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