×
Namespaces

Variants
Actions
Revision as of 05:07, 15 June 2012 by hamishwillee (Talk | contribs)

Memory leak repeatedly adding elements with Image in List item, "refreshing List" (J2ME, S60)

From Nokia Developer Wiki
Jump to: navigation, search



Article Metadata
Tested with
Devices(s): N91, N95, Nokia 6233
Compatibility
Platform(s): S60 - all
Series 40
Symbian
Article
Created: Tiger79 (01 Jul 2009)
Last edited: hamishwillee (15 Jun 2012)

Overview

Applications using a MIDP 2.0 List item using elements with Images to fill the List repeatedly will cause a Memory Leak and thus will force the application to shut off.

Update

After some testing on the Nokia 6233 (Series 40) I noticed that even there the memory usage keeps incrementing, the difference though is that the Garbage COllector does it's job just before going OutOfMemory, which might indicate a problem with the S60's Garbace Collector's implementation ???


Description

When using a List, with several elements (25+), each element using the SAME Image, and the List gets repeatedly refreshed the used memory of the application will keep increasing in S60 devices.


How to reproduce

  • Create a data Source (for example a Vector)
  • Fill it with some data, preferably something like 25+ items (Strings for example)
  • Afterwards create one instance of an Image
  • Fill the List with the Vectors data and the Image (i.e : List.append(String, Image);)
  • Repeatedly Fill the List by looping through last point.
  • Memory will keep increasing only in S60 devices (tested on a Nokia 6233 S40 and will run indefinitely just fine)




Source code :

testList.java

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
/**
* @author Tiger79
*/
public class testList extends MIDlet implements CommandListener
{
private Display mDisplay;
private Form myForm;
private Command exitCmd, showCmd;
private theList myList;
private StringItem myString, myFreeMemory, myUsedMemory;
 
public void startApp()
{
mDisplay = Display.getDisplay(this);
 
myList = new theList(this);
 
myForm = new Form("Little test");
 
exitCmd = new Command("Exit", Command.EXIT, 0);
showCmd = new Command("Show List", Command.SCREEN, 0);
 
myForm.addCommand(exitCmd);
myForm.addCommand(showCmd);
 
myForm.setCommandListener(this);
 
myString = new StringItem("Loops : ", "");
myFreeMemory = new StringItem("Free Memory : ", "");
myUsedMemory = new StringItem("Used Memory : ", "");
 
myForm.append(myString);
myForm.append(myFreeMemory);
myForm.append(myUsedMemory);
 
showMidlet();
}
 
public void pauseApp()
{
}
 
public void destroyApp(boolean unconditional)
{
}
 
public void commandAction(Command c, Displayable d)
{
if(c == exitCmd)
this.notifyDestroyed();
else if(c == showCmd)
mDisplay.setCurrent(myList);
 
}
 
public void setValue(int passedValue)
{
myString.setText(String.valueOf(passedValue));
myFreeMemory.setText(String.valueOf(Runtime.getRuntime().freeMemory()/1024));
long temp = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
myUsedMemory.setText(String.valueOf(temp/1024));
 
}
 
public void showMidlet()
{
mDisplay.setCurrent(myForm);
}
}


theList.java

import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;
 
 
/**
*
* @author Tiger79
*/
public class theList extends List implements CommandListener
{
private Vector myVector; //Vector with Strings to be shown in List
private Image myImage; //the culprit : an Image, just instanced once
private Timer fillTimer = new Timer(); //Timer to perform a refresh of the List every x seconds
private fillTask fillItTask = new fillTask(); //the task Class which performs the refresh
public int counter = 0; //counter that counts how many refreshes have been done
private testList myMidlet; //callback to Midlet
private Command backCmd;
 
public theList(testList mMidlet)
{
super("testing", List.IMPLICIT);
myMidlet = mMidlet;
 
myVector = new Vector();
 
try
{
myImage = Image.createImage("/littleImage.png");
}
catch(Exception ex)
{
System.out.print("Problem creating Image : " + ex.toString());
}
 
backCmd = new Command("Back", Command.BACK, 0);
this.addCommand(backCmd);
setCommandListener(this);
 
for(int i = 0 ; i < 25; i ++)
myVector.addElement( i + " - TestData, just some testData to test the testing thingie");
 
fillTimer.scheduleAtFixedRate(fillItTask, 0, 1000);
 
}
 
private void fillList()
{
this.deleteAll();
for(int i = 0; i < myVector.size(); i ++)
append((String)myVector.elementAt(i), myImage);
counter++;
myMidlet.setValue(counter);
}
 
private class fillTask extends TimerTask
{
public final void run()
{
fillList();
}
}
 
public void commandAction(Command c, Displayable d)
{
if(c == backCmd)
{
myMidlet.showMidlet();
}
}
}
  • This Image can be used :

LittleImage.png

Solution

just don't refresh that List item very often ;)

Test Results

  • Nokia N95 : around 615 refreshes
  • Nokia N91 : around 197 refreshes
  • Nokia 6233 (S40) : I stopped etsting after 3700 refreshes, no problems here

Reference

27 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×