Memory problem with JTextFields
Hello,
I have a wierd problem with JTextField and the memory.
I need to fill a JPanel with different Components (including JTextFields), then do some calculation, remove the Components and filling the JPanel again.
When i so this too often my i get an OutOfMemory Exception. I narrowed to problem down and wrote a small sample program to demonstrate the problem.
When i call the method doIT (where the Panel is repeatedly filled) from the main-function everything works fine, but when it is called as a result from the GUI-Button-Event the memory for the JTextFields is not freed (even the call of the Garbage collector changes nothing)
When i only use JButtons to fill the Panel everything works fine.
Has anyone an idea why this problem occurs and how i can work around it?
[Edit] I tested it whith java 1.5.0_06, 1.5.0_11, 1.6.0_02
Thanks
Marc
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JTextField;
publicclass MemoryTestDLGextends JDialog{
public MemoryTestDLG(Frame owner){
// create Dialog with one Button that calls the testMethod
super(owner);
JButton b =new JButton("doIT ...");
b.addActionListener(new ActionListener(){
publicvoid actionPerformed(ActionEvent e){
doIT();
setVisible(false);
}
});
getContentPane().add(b);
pack();
}
publicvoid doIT(){
// Testmethod that fills a JPanel 20 times with Components and clears it
// again
JPanel p =new JPanel();
long memUse1 = 0;
long memUse2 = 0;
long memUseTemp = 0;
for (int count = 0; count < 20; count++){
// Clear the panel
p.removeAll();
// Get memory usage before the task
Runtime.getRuntime().gc();
memUse1 = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
.getUsed();
// Fill Panel with components
for (int i = 0; i < 200; i++){
// The Buttons seem to be released without any problem
p.add(new JButton("test" + Math.random()));
// JTextFields are not released when used from the dialog.
p.add(new JTextField("test " + Math.random()));
}
// get memory usage after the task
Runtime.getRuntime().gc();
memUseTemp = memUse2;
memUse2 = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
.getUsed();
// print Memory results
System.out.println("Memory Usage: " + f(memUse1) +"->"
+ f(memUse2) +" [ Used:" + f(memUse2 - memUse1)
+" ] [ Freed: " + f(memUseTemp - memUse1) +"]");
}
}
public String f(long m)// formats the output
{
String s ="" + m;
while (s.length() < 8)
s =" " + s;
return s;
}
publicstaticvoid main(String[] args){
MemoryTestDLG d =new MemoryTestDLG(null);
System.out
.println(" Direct Call (all is OK) -");
d.doIT();// Memory is freed with every call to JPanel.removeAll()
System.out
.println(" Call from Dialog (memory is not freed) -");
// The Memory keeps blocked
d.setModal(true);
d.setVisible(true);
System.exit(0);
}
}
Message was edited by:
marcvomorc
# 1
I've run your code almost fifteen times and have not run out memory. I realised the memory is only being released when the objects are not visible on the screen. However, when the button is clicked, there is huge (in the 800000's) amount memory released at once. Also running Task Manager, it shows that amount of memory assigned to the app is virtually the same all through. Maybe it has something to do with your system. I'm running JDK 6.0 on Windows Vista 32bit, with 1Gb RAM
Here is your slightly modified doIT method. modified for graphical display only.
public void doIT() {
// Testmethod that fills a JPanel 20 times with Components and clears it
// again
JPanel p = new JPanel( new GridLayout(0,2) );
long memUse1 = 0;
long memUse2 = 0;
long memUseTemp = 0;
for (int count = 0; count < 20; count++) {
// Clear the panel
p.removeAll();
p.validate();
p.repaint();
// Get memory usage before the task
Runtime.getRuntime().gc();
memUse1 = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
.getUsed();
// Fill Panel with components
for (int i = 0; i < 200; i++) {
// The Buttons seem to be released without any problem
p.add(new JButton("test" + Math.random()));
// JTextFields are not released when used from the dialog.
p.add(new JTextField("test " + Math.random()));
}
// get memory usage after the task
Runtime.getRuntime().gc();
memUseTemp = memUse2;
memUse2 = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
.getUsed();
// print Memory results
System.out.println("Memory Usage: " + f(memUse1) + "->"
+ f(memUse2) + " [ Used:" + f(memUse2 - memUse1)
+ " ] [ Freed: " + f(memUseTemp - memUse1) + "]");
}
getContentPane().add( new JScrollPane(p), BorderLayout.CENTER);
getContentPane().validate();
getContentPane().repaint();
}
ICE
# 2
Thank you for your answer,
In this sample the programm does not run out of memory. But when you look at the output you see, that in the first run (direct call) the memory ist freed immediately when tha panel is cleared but in the second run (from the Button) the memory usage is getting bigger and bigger. Wenn you change the number of components to 2000 (4000)
//... ....
// Fill Panel with components
for (int i = 0; i < 2000; i++) {
// The Buttons seem to be released without any problem
//... ...
and use the default memory settings (69mb heap) the programm runns out of memory.
I get the following output:
Direct Call (all is OK) -
Memory Usage:445504-> 8121016 [ Used: 7675512 ] [ Freed: -445504]
Memory Usage:617352-> 8114336 [ Used: 7496984 ] [ Freed: 7503664]
Memory Usage:810488-> 8491768 [ Used: 7681280 ] [ Freed: 7303848]
Memory Usage:943704-> 8114976 [ Used: 7171272 ] [ Freed: 7548064]
Memory Usage:836760-> 8505072 [ Used: 7668312 ] [ Freed: 7278216]
Memory Usage:978352-> 8114784 [ Used: 7136432 ] [ Freed: 7526720]
Memory Usage:835552-> 8498288 [ Used: 7662736 ] [ Freed: 7279232]
Memory Usage:977096-> 8114312 [ Used: 7137216 ] [ Freed: 7521192]
Memory Usage:835640-> 8498376 [ Used: 7662736 ] [ Freed: 7278672]
Memory Usage:977296-> 8115000 [ Used: 7137704 ] [ Freed: 7521080]
Memory Usage:835392-> 8504872 [ Used: 7669480 ] [ Freed: 7279608]
Memory Usage:976968-> 8115192 [ Used: 7138224 ] [ Freed: 7527904]
Memory Usage:836224-> 8501624 [ Used: 7665400 ] [ Freed: 7278968]
Memory Usage:977840-> 8115120 [ Used: 7137280 ] [ Freed: 7523784]
Memory Usage:835664-> 8498256 [ Used: 7662592 ] [ Freed: 7279456]
Memory Usage:976856-> 8114384 [ Used: 7137528 ] [ Freed: 7521400]
Memory Usage:835784-> 8502848 [ Used: 7667064 ] [ Freed: 7278600]
Memory Usage:977360-> 8114592 [ Used: 7137232 ] [ Freed: 7525488]
Memory Usage:835496-> 8502720 [ Used: 7667224 ] [ Freed: 7279096]
Memory Usage:976440-> 8115128 [ Used: 7138688 ] [ Freed: 7526280]
Call from Dialog (memory is not freed) -
Memory Usage:866504-> 8784320 [ Used: 7917816 ] [ Freed: -866504]
Memory Usage: 7480760->14631152 [ Used: 7150392 ] [ Freed: 1303560]
Memory Usage: 14245264->22127104 [ Used: 7881840 ] [ Freed:385888]
Memory Usage: 19302896->27190744 [ Used: 7887848 ] [ Freed: 2824208]
Memory Usage: 27190744->35073944 [ Used: 7883200 ] [ Freed:0]
Memory Usage: 31856624->39740176 [ Used: 7883552 ] [ Freed: 3217320]
Memory Usage: 39740176->47623040 [ Used: 7882864 ] [ Freed:0]
Memory Usage: 44410480->52293864 [ Used: 7883384 ] [ Freed: 3212560]
Memory Usage: 52293864->58569304 [ Used: 6275440 ] [ Freed:0]
Memory Usage: 58569304->64846400 [ Used: 6277096 ] [ Freed:0]
Exception occurred during event dispatching:
java.lang.OutOfMemoryError: Java heap space
when I outcomment the adding of the JButtons the amount of freed memory is 0 in the second run. So my guess is, that there is a problem with freeing the memory for the JTextFields.
Memory Usage:447832-> 6509960 [ Used: 6062128 ] [ Freed: 6332768]
Memory Usage:722776-> 6785632 [ Used: 6062856 ] [ Freed: 5787184]
Call from Dialog (memory is not freed) -
Memory Usage:468880-> 6770240 [ Used: 6301360 ] [ Freed: -468880]
Memory Usage: 6770240->13016264 [ Used: 6246024 ] [ Freed:0]
Memory Usage: 13016264->19297080 [ Used: 6280816 ] [ Freed:0]
Memory Usage: 19297080->25570152 [ Used: 6273072 ] [ Freed:0]
Memory Usage: 25570152->31849160 [ Used: 6279008 ] [ Freed:0]
Memory Usage: 31849160->38124368 [ Used: 6275208 ] [ Freed:0]
Memory Usage: 38124368->44402072 [ Used: 6277704 ] [ Freed:0]
Memory Usage: 44402072->50677928 [ Used: 6275856 ] [ Freed:0]
Memory Usage: 50677928->56955880 [ Used: 6277952 ] [ Freed:0]
Memory Usage: 56955880->63232152 [ Used: 6276272 ] [ Freed:0]
Exception occurred during event dispatching:
java.lang.OutOfMemoryError: Java heap space
Additionally the JPanel I am using is not displayed on the screen. It stays invisible the whole time, but i cannot work around that, because the calculation is depending on the values being in components on the JPanel)
Marc
# 3
Well I'd suggest you switch to less memory hungry approach and use a JTable or some other multiple row data component to store the values for calculations and not result to using multiple text fields. With JTable you can display up to about 30000 rows without too much memory loss. (Unless this is not your requirement.). You could even only use the TableModel as your data store since you do not need the display and do you calculations with that.
ICE