Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4203912
Votes 116
Synopsis JTextArea uses too much memory (if large byte array passed to cto=
Category java:classes_swing
Reported Against 1.2 , 1.3 , 1.2.2 , 1.4.2 , 1.2rc1
Release Fixed 1.5(tiger-b28)
State 10-Fix Delivered, bug
Priority: 4-Low
Related Bugs 4257720 , 5089193
Submit Date 19-JAN-1999
Description



=20
While writing a simple file viewing class, I
encountered a problem regarding the necessary
memory. For example, if I do something like ...

//---------------------------------------------
// 'sb' is a byte array with some text
//      read from a file
//
    JTextArea ta=3Dnew JTextArea(new String(sb));=20
//
// OR !
//
    JTextArea ta=3Dnew JTextArea();
    ta.setText(new String(sb));
//
//---------------------------------------------

the amount of memory needed is incredible.

Let=B4s say, the size of 'sb' is 2 MB, then the
memory allocated for the JTextArea instance is
something like 25,8 MB. This memory usage is
almost linear, a text twice the size (4 MB)
causes 51,4 MB to be allocated.=20

The same happens, if I use a JEditorPane instead
of a JTextArea.

I consider this to be a bug, because this amount
of memory is just too much to be reasonable,
considering that only plain text is displayed.

I experience this behaviour in JDK 1.1.5 with
Swing 1.0.2, JDK 1.1.7 and 1.2RC1.
(Review ID: 43400)
======================================================================




Swing Text Components(JTextArea, JTextField...) seem to leak 
memory as measured by WindowsNT Task Manager Memory Usage 
History when given focus.  Leak does not occur when focus is lost
or when their AWT counterparts are used, as demonstrated in the
following code:

import java.awt.*;
import javax.swing.*;

public class SwingTextMemoryTest extends JFrame{

	private JPanel panel;
	private JTextField jTextField;
	private TextField textField;
	
	public SwingTextMemoryTest()
		{
		 super();
		 panel = new JPanel();
                 jTextField = new JTextField("JTextField",15);
		 textField = new TextField("AWT TextField",15);
		 panel.add(textField); // Stable with focus
		 panel.add(jTextField); // Leaks when given focus
		 this.getContentPane().add(panel);
		 setSize(500,500);
		 setVisible(true);
		}
	
	public static void main(String[] args)
		{ SwingTextMemoryTest test = new SwingTextMemoryTest(); }

}

Thank you for your attention.

- Mark Horwath
(Review ID: 83582)
======================================================================




java version "1.2.2"
Classic VM (build JDK-1.2.2-W, native threads, symcjit)


When calling setText() on a JTextArea, * with a huge string as the argument * (
say 2.6 MB ), the memory usage shoots up by atleast 30-35 MB.

The code I enclosed :-   There is a JFrame, with a JPanel containing a
JTextArea ( enclosed in a JScrollPane ) as the contentpane.  A file name is
specified as the command line argument.  The program opens the specified file,
reads its contents, and calls setText() on the JTextArea.  When the input file
is small ( say around 1 MB ), there is no problem, but when I gave a input file
of size 2.6 MB, the memory usage went up to 45 MB.  This happened on JDK1.2.2
both in Windows NT and Solaris.  ( I have 128 MB RAM in my machine ).


Code: ////////////////////////////////////////////////////////////////////////

import java.awt.* ;
import java.awt.event.* ;

import javax.swing.* ;
import javax.swing.event.* ;

import java.io.* ;

class JTextAreaTest  {
	JFrame f = new JFrame("Test") ;
	JTextArea ta = new JTextArea(30,30) ;
	JPanel mainPanel = new JPanel() ;
	String m_fileName ;
	StringBuffer contents = new StringBuffer() ;
	
	JTextAreaTest(String fileName)   {
		m_fileName = fileName ;
		setupTextArea() ;
		JScrollPane tempPanel = new JScrollPane(ta) ;
		f.getContentPane().add(tempPanel);

		f.addWindowListener(new WindowAdapter()   {
			public void windowClosing(WindowEvent e)  {
				f.dispose() ;
			}
		});
		
		f.pack() ;
		f.show() ;
	}


	private void setupTextArea()   {
		BufferedReader in = null ;
		try  {
			in  =  new BufferedReader(new FileReader(m_fileName));
		}
		catch (FileNotFoundException e)  {
			e.printStackTrace() ;
			return ;
		}

		String curLine = null ;

		while (true)  {
			try  {
				curLine = in.readLine() ;
	  
			}
			catch (IOException e)  {
				e.printStackTrace() ;
			}

			if (curLine == null)  {
				break ;
			}
			contents.append(curLine);
			contents.append("\n");
		}
		try {
			in.close();
		}
		catch (IOException e)  {
		  e.printStackTrace() ;
		}

		ta.setText(contents.toString());
	}

	public static void main(String[] args)    {
		if ( args.length != 1)  {
			System.out.println("Usage: java JTextAreaTest
<fileName>" );
			System.exit(1);
		}
		JTextAreaTest taTest = new JTextAreaTest(args[0]) ;
	}
}

/////////////////////////////////////////////////////////////////////////
(Review ID: 99331)
======================================================================
Work Around
N/A
Evaluation
SUMMARY: The huge kinds of wastage reported could not be reproduced under 1.2.1. I did however see an approximately 2x memory usage over what I expected or could easily explain away.

DETAILS:
This bug did not come with an executable code example.  I created my own test which is attached below. I have also attached an hprof dump that shows the memory allocations in detail. (I have not included my results as reported by the prgoram as they duplicate whats in the hprof and can be easily reonstructed by running the test under 1.2.1)

The results are that JTextArea appears to require 4 bytes per character.  2 bytes is understandable in that Java is unicode internally. The other 2 bytes I could not as easily dismiss so I did not retire this bug.

  xxxxx@xxxxx   1999-04-29

---------------------------------------------------
Looking at the output from -Xhprof seemed to indicate that it was the GapBuffer class which was allocating all the memory in question.  The sample program creates a String w/ 2 million characters.  You'd expect that to need 4Meg to store (unicode can be a pain), but instead the GapBuffer allocates a char[] which is 8Meg in size.
  xxxxx@xxxxx   1999-04-29

GapBuffer will allocate up to twice the amount of needed storage when it
resizes to try to prevent excessive resize requests which are expensive.
For 2 meg bytes, the buffer will store 4 meg characters, and if twice the
size needed that would add up to 8meg.  Also managed by the GapBuffer is
the set of Position objects that make up the line map.  These are done
in a funcky way to get weak references on 1.1 in a platform independant
way.  These could be changed to use weak references in 1.2 and would
probably be cheaper.  Also, positions representing the same location could
be shared which would reduce the number of posistion objects since there
are typically at least two from the edges of two elements butting up to
each other.  The resize strategy could be less aggressive when getting
large and this would reduce the overall array.

-----
Fix for 4525843 improves memory consumption. 
we are using weak references now. Positions for the same location are shared.

On some simple test cases memory footprint is reduced by 50%

  xxxxx@xxxxx   2002-06-20




    Also for each line in PlainDocument the following data
structures are created  :
    . instance of javax.swing.text.AbstractDocument.LeafElement (32 bytes)
    . instance of javax.swing.text.GapContent.StickyPosition (48 bytes)
      (only one instance since Position sharing is used)
    . entry in array
    javax.swing.text.AbstractDocument.BranchElement.children (4 bytes)

    The intensive memory growth could also be visibly because of
storage array reallocating which causes intensive VM heap growth.
    The possible decision could be changing storage array resize
policy in GapContent class. For example it could be the same as
in GapVector ((requredSize + 1) * 2) when the size of text content
is less than 1Mb, but when this size is exceeded we could increase
the array size just by 1Mb when required. This slightly decreases
performance (due to more frequent array reallocation) but also
decreases the amount of unused memory in the most cases.


======================================================================
Comments
  
  Include a link with my name & email   

Submitted On 27-MAY-1999
xhunterx
The memory leak here seems independent of the size
of the text string and inherent to Swing text
components in general, not simply JTextArea.
Try invoking WinNT Task Manager and watch the
memory usage history while running an app or 
applet with just an empty JTextField and an empty
AWT TextField. You will find that the AWT text
component remains watertight, whereas the Swing
text component leaks linearly - seemingly with no 
upper bound - when given the focus.
- Mark Hunter


Submitted On 31-JAN-2001
jjbad
The memory leak still exist in the JDK 1.3.  I too am on a 
Windows NT box with 192 MB RAM.  I noticed the leak using 
the Windows NT task manager's Processes tab.  My APP with 
the VM (denoted by the java.exe process) are taking up the 
~12 MB.  When I loaded a 3.8 MB TXT file, memory usage 
shoots up to 70 MB.  That is incredible.  I confirmed the 
problem by running the Notepad example in the JDK 1.3
\demo\jfc\Notepad directory.  The Notepad also leaks 
memory.  I opened the same file and it took up 70 MB.  This 
is not surprising since it too is using the JTextArea 
component.  In some instances I got an OutOfMemoryError.  
Both my APP and the Notepad exceeded the limit of the VM 
Heap size.  I toggled the -Xmx switch to compensate for now.

What is the status of this problem.

-- John Blum


Submitted On 04-MAY-2001
exejmoore
We have definitely noticed this issue with JDK1.3.  When I 
try to display a 7MB XML file for the user to edit, my 
WinNT task manager shows a jump from 30MB(after reading the 
file into a string) up to 122MB!! We told our clients they 
only need 128MB for our app so we set the VM size at 96MB, 
but as you can see they get an Out of Memory error real 
quick.


Submitted On 09-MAY-2001
jwrobel
There are two independent problems reported for this bug ID.  I think that they should be separated into 
two different bugs.  One problem is that JTextArea seems to allocate too much storage when initialized with 
data.  The other (IMO more serious) bug is that memory is eaten up at an alarming rate just by giving a 
JTextArea focus.  There needn't be any data at all in the field.

The Sun evaluation only addresses the first problem.  I'm wondering whether anyone there is really even 
aware of the second problem.

My guess is that the focus leak is related to whatever code it is that makes the cursor blink.

- Jeff Wrobel


Submitted On 07-JUN-2001
xhunterx
Of note:

I agree with Jeff that the Bug ID should be split for tracking purposes; clearly there are two distinct isuues 
(and two sets of impacted users) here.  Fortunately, the "slow leak" Bug seems to have been addressed at 
some point between J2SE releases 1.2.2 and 1.3.0 as neither the latter nor 1.4beta1 exhibit the behavior.


Submitted On 05-JAN-2002
karlik1
I understand the GapBuffer's responsibility and why it is
doing things the way it is.  But clearly it is allocating
way too much additional memory.  While doubling the size of
the array is a nice simple way to go, might I recommend
that you "govern" the increase, such as "double the size
of the array, or increase the array by .5Meg, whichever
is the smaller amount"?


Submitted On 06-JUN-2002
hellerSTH
Is there any workaround or replacement for a class (e.g. modified GapBuffer class), I have the problem that opening a 10-15MB file freezes the whole machine and ends in an out of memory exception after some minutes..


Submitted On 14-JUN-2002
mthornton
In addition to the extra space allocated for the gap in the 
content, a considerable amount is required to hold the line 
structures. In 1.4 this amounts to a total of at least 92 
bytes for each line (on top of the character data itself).
This is made of a LeafElement (24 bytes), 2 MarkData (16 
each) and 2 StickyPosition (12 each) plus slots in arrays 
for Elements and MarkData.
Thus if we have short lines of say 20 characters, this will 
require about 132 bytes per line for an inflation ratio 
(over ascii bytes) of 6.6.


Submitted On 20-SEP-2002
adriskill
I'm using Java 1.4.1-rc1, and I'm seeing JTextArea average 
6.7 bytes per character plus 278 bytes per line.


Submitted On 30-DEC-2002
SpoonMan
i am using sdk1.4.1_01, and the bug is still present in
jtextarea. it is also present in jeditorpane and jtextpane.


Submitted On 10-JAN-2003
charlie76
I ran into this same problem, but when I loaded a 2MB file my 
test application soared to 65MB!  I ran it under OptimizeIt, 
and discovered most of the memory was taken up by 
java.lang.ref.Finalizer.  Over 394,000+ of these things!

Looking into the PlainDocument object I saw that within 
AbstractElement and GapBuffer both have finalize method.  
This is what is causing these classes to allocate 394,000+ 
Finalizers.  Then they hang around until the Finalizer thread 
can actually keep up with the excessive allocation.

Just get rid of the finalize method, and I think this would stop 
being a problem.  Let the 1.1 VMs leak so 1.2, 1.3, 1.3.1 and 
all the 1.3.1_0x, 1.4.0, 1.4.1, and future VMs will not!  
Sacrfices for backward compability for crappy platforms are 
just that.  Backwards!


Submitted On 25-JAN-2003
jessh
Okay, supposedly there was a 50% memory footprint 
reduction on 2002-06-10, yet: (1) this bug is still open and 
(2) there has been no indication of this fix in any Java 2 
v1.4.1_0x JVM release.

Why do such important bug fixes take so long (it's been over 
6 months) to get into a patch release?


Submitted On 25-JAN-2003
jessh
P.S. Fixing this would seem to provide a nice boost to heavy 
text applications, e.g. NetBeans / Sun ONE Studio -- please 
release this fix Sun, it is your own interest unless you want to 
give the Eclipse folk ammo against you (besides giving MS, 
etc, even more ammo)


Submitted On 28-APR-2003
janosch76
I think, the reason for the huge memory-usabe of JTextComponent is 
it's document view architecture. For every-line in the text a 
element/view pair is created (+ all views/elements must be stored in an 
collection). This takes up a huge amount of data if the text conatins a 
lot of lines.
A second problem occurs during putting the text into the text 
component using JTextComponent.setText(). The method will not use 
the passed string directly. Instead it will first make a copy of it. So the 
the amount of memory needed to set a text is at least twice the text's 
size. 
The only solution for this bug I can think of, is to write a custom 
TextComponent. I wrote a simple textviewer, which is captable of 
displaying a bigger amount of text then JTextComponents are captable. 
But the component is only for displaying and not editing text. 


Submitted On 10-MAY-2003
jessh
Can we get the 2x memory usage portion of this issue fixed
in a released JVM one of these days?


Submitted On 14-JUL-2003
mthornton
I have written a Document class which allows me to view 
files of 15MB (over 300000 lines) using the standard 
JTextArea without any memory problems. With a little more 
work (loading the document in the background) I hope to be 
able to handle the 100MB+ trace files I sometimes create.
For general use on typical files (less than say 100KB), the 
existing document classes work well. JTextArea seems to 
work well on any size document. So for large documents we 
just need some specialised document classes.
My experimental classes have the following properties
1) The document is read only
2) The file is memory mapped using the nio classes
3) I parse the file quickly to locate lines, but only store their 
position in an int[] (no object created per line). Line 
elements are only created on request
4) The mapped byte buffer is decoded into characters on 
demand (and the decoded blocks cached). This only works 
with some character encodings.

I hope this helps anyone still trying to cope with large 
documents.


Submitted On 16-JUL-2003
sachinvshah
HI,

I am also facing the similar problem with JEditorPane. When i 
try to show a file which is more then 2.5M i get 
outOfMemoryError.

Does any one have any workaround for the same.

Sachin 


Submitted On 24-JUL-2003
jessh
I just realized that I'd misread the last bit of the evaluation 
when I previously visited this bug.  The 50% memory footprint 
reduction was separately tracked via bug #4525843 -- and 
was fixed in 1.4.2.

That's good enough for me for now.


Submitted On 19-AUG-2004
MartinHilpert
Still occurs in JDk 1.4.2_05. Here's simple test code:

System.out.println("sb len: "+sb.length()); //7 MB
System.out.println("used mem before setText(): "+(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); //10 MB
                    textArea.setText(sb.toString());
                    sb.setLength(0);
                    sb = null;
System.out.println("used mem after setText(): "+(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); //65 MB!!!

You will see that after setText() (or also using textArea.append()) the JVM memory usage suddenly jumps way off the required space.


Submitted On 16-OCT-2007
ElmerHomero
This problem still ocurrs in jdk 1.6; i can't use java because this problem. Using the code showed in bug #4257720 the memory used only decrease 20 mb. In my aplication i'll use 10 jtextpane to show big files. I can't use this.



PLEASE NOTE: JDK6 is formerly known as Project Mustang