JDK-4448451 : JEditorPane leaks memory when the setPage() method is called with a URL.
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2001-04-19
  • Updated: 2003-02-04
  • Resolved: 2003-02-04
Related Reports
Duplicate :  
Description

Name: yyT116575			Date: 04/19/2001


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

When attempting to load a URL into the JEditorPane using the setPage() method,
memory leaks at a rate relative to the size of the information contained at the
URL being viewed.
  Note that the intended application would need to reload information from the
same URL on a continuous, extended basis, without caching the page.  Hence the
use of the "NonCachingEditorPane" subclass to defeat caching of the document.

The following code will leak memory at a rate of about 1mb/sec when provided
with a suitable html document (one with say- 1000 lines of text).  Adjusting
the rate of reloading will of course lessen the impact of the loss, although
it does not provide a solution in an extended use scenerio.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.text.*;
import java.io.*;
import java.net.*;

public class MemoryLeaker extends JPanel {
  NonCachingEditorPane jt = new NonCachingEditorPane();
  JScrollPane pane = new JScrollPane();
  JTextField input = new JTextField("file:C:\\test.html");
  URL url;
  private javax.swing.Timer refresher = new javax.swing.Timer( 500,
      new ActionListener(){
        
        String charSetSpec = "text/html";
        public void actionPerformed( ActionEvent a ) {
          try {
            jt.setPage( url );
          } catch( IOException ex ) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog (MemoryLeaker.this, 
                "Couldn't read " + input.getText(), "Invalid Input",
                JOptionPane.ERROR_MESSAGE);
            refresher.stop();
          }
        }
      }
  );

  public MemoryLeaker() {
    setLayout (new BorderLayout (5, 5));

  
    pane.setBorder ( BorderFactory.createLoweredBevelBorder());
    pane.getViewport().add(jt);
    add(pane, BorderLayout.CENTER);
    add (input, BorderLayout.SOUTH);

    input.addActionListener (new ActionListener() {
      public void actionPerformed (ActionEvent e) {
        try {
          url = new URL( input.getText() );
          jt.setPage( url );

        } catch ( Exception mfurl ){ mfurl.printStackTrace();}
    
        refresher.start();
      }
    });
  }
  public static void main( String[] args ) {
    JFrame frame = new JFrame( "MemoryLeaker" );
    frame.getContentPane().setLayout( new BorderLayout() );
    frame.getContentPane().add( new MemoryLeaker(), BorderLayout.CENTER );
    frame.setSize( 800, 600 );
    frame.setVisible( true );
    frame.addWindowListener( new WindowAdapter() {
      public void windowClosing( WindowEvent e ) {
        System.exit( 0 );
      }
    });
    
  }
  class NonCachingEditorPane extends JEditorPane {
    public URL getPage() {
      return null;
    }
  }
}

Procedure to reproduce the memory leak:
1. Take the attached file (test.html), put it on your drive where you can
find it.( or another suitable file if you like).
2. Compile the code in MemoryLeaker.java
3. java MemoryLeaker
4. Enter the name of the file you would like to load as a URL in the
textfield at the bottom of the application.
5. Press enter.
6. Monitor your memory usage via your O.S., or wait for a
java.lang.OutOfMemoryError.

I have produced this problem on a PC.  My boss, on a SunBlade, 
running Solaris, with a similar application that he wrote without 
seeing my code, reproduced the leak as well.
(Review ID: 120936) 
======================================================================

Comments
EVALUATION There is no attached file "test.html" and any attempt I make at creating a sample file leads to exceptions when I run the test. Moving to imcomplete and sending e-mail to try to track down a copy of this "test.html". shannon.hickey@Eng 2001-07-11 The required files have been attached to the bug report. I was not able to reproduce the problem on my own machine with any JDK version. However, it was reproduced for me by the Sun contact for this bug. I do not beleive this to be a Swing problem but rather a HotSpot or gc problem. Re-assigning to HotSpot. Please see the comments section for more information. shannon.hickey@Eng 2001-07-23 Yes, it does leak. ran with -Xint and by morning the process was using 150 M instead of 120M were it had started. I could not run the test with any other version of the VM but 1.4. Assining to gc sub catagory fro further investigation... mohammad.gharahgouzloo@Eng 2001-07-26 I've been running with JDK-1.4.0-beta2-b76 on both my WindohNT box and my SolSparc box for almost 5 hours, and neither of them looks like they are leaking memory at any signficant rate. The Windohs box has grown the heap to 64MB, and seems to be accumulating live memory in the old generation, but applications are allowed to do that. Periodically full collections reduce the heap to less than 30MB, so there seems to be a lot of memory that gets held onto for much longer than the refresh rate of the application. If that memory accumulates to the point where it requires more than 64MB, I will get an OutOfMemoryError, but that's the right thing to have happen. The SolSparc box hanging out with only a 16MB heap after the same 5 hours. That could mean that the SolSparc code releases its garbage sooner so the collector can collect it. Or it could be that SolSparc is enough slower than Windohs that it just hasn't gotten as much work done, so it hasn't generated as much garbage. One big difference is that my SolSparc box is a multi-processor, so if there's background cleanup work (e.g., finalizers), they may run uninterrupted on SolSparc, but be competing with the main Java thread on Windohs. Would yungching.young@Eng please try running on the machine that fails with -XX:+PrintGC -XX:+PrintGCTimeStamps to get a (very long) trace of what the collector is doing and when? That will help me track down what's happening. Thanks. The Comments section says that "the memory usage will increase from 89MB to more than 160MB". That can't be Java heap memory usage, which has a default maximum of 64MB, unless you give a -Xmx argument on the command line. My Windohs box with the 64MB heap is running in 80MB of virtual memory, and my SolSparc box with a 16MB heap is running in 130MB of virtual memory. But those figures haven't changed significantly since the applications stabilized their memory requirements. ###@###.### 2001-08-16 Aha! I just pushed my Windohs run ober the edge, by bringing up StarOffice to try to analyze the heap size data I was getting. After crusiing along at <30MB of live data in a 64MB heap for almost an hour, the live data for MemoryLeaker grew to 64MB and I got an OutOfMemoryError. I think the problem is that there's a background thread that's needed by MemoryLeaker to clean up after the foreground thread (it could be finalization), and that thread gets starved when there are other things happening on the machine. (I tried provoking the same behavior on my SolSparc box, but that's a dual-processor (and the OS is probably better at thread scheduling) so it doesn't seem to have the same failure. Would someone confirm that MemoryLeaker runs okay on a dual-processor, and that it runs okay on an otherwise idle single-processor, and that it can be made to fall over on a single-processor if you have other CPU-intensive things going on? Thanks. ###@###.### 2001-08-16 I'd like Steve Wilson to take a look at this one before I close it as "not a bug". ###@###.### 2001-08-22 I'm about to close this as "not a bug" unless someone tells me soon that my evaluation (above) is wrong. ###@###.### 2001-09-14 Jane is suggesting we (JEditorPane) call close on the InputStream, which is why this ended up back in Swing land. ###@###.### 2001-10-03 Igor, I beleive there's two issues to be looked at here. The first is about closing the InputStream. The second relates to a fix that you did recently with GapContent and weak references. According to a post on the JDC, that may have been the problem. Also, it has been suggested by ###@###.### in this bug's comments section that we may have been falling behind on finalization. That seems consistent with your fix to GapContent. ###@###.### 2002-08-05 Name: ik75403 Date: 02/04/2003 I was running the test case in optimizeIt for a night and do not see memory leaks. As Shannon mentioned there were two problems probably. The first one (GapContent and weak references) was fixed by the fix for 4525843. The second one (closing input stream) was fixed in 1998/07/01 Closing the bug as dup of 4525843. (4525843 is fixed and integrated. Can not close 4525843 as a dup of this one) ======================================================================
11-06-2004