ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  makeImage() memory leak java
Posted by Greg B on Aug-30-2011 23:25
Hey guys

  I have a problem with the following code causing a memory leak and NetBeans profiler points me directly to these methods...  I was using

viewer.setImage(c.makeImage());
viewer.setImageMap(c.getLegend().getHTMLImageMap("clickable","","title='{label}'");

to render our graphs but have switched to

// Output the chart
Image temp = c.makeImage();
String tmp = c.getLegend().getHTMLImageMap("clickable", "","title='{label}'");
viewer.setImage(temp);
viewer.setImageMap(tmp);
temp = null; tmp = null;
viewer.disposeReference();

Now this has taken me from an app growing by 25 MBs of memory usage in 20 mins to only growing by 6 MBs over 8-10 hours.... but it is still growing and the application is running against an empty database at this point in order to isolate my leaks. I update every 5 seconds or so and i would like to eliminate the leak alltogether.. i am relatively new to ChartDirector and wonder if i am using this wrong?

  Re: makeImage() memory leak java
Posted by Greg B on Aug-30-2011 23:26
I tried to include a snapshot of profiler showing makeImage as the culprit but it wouldn't go

  Re: makeImage() memory leak java
Posted by Peter Kwan on Aug-31-2011 00:49
Hi Greg,

Note that the forum only allows attachment of less than 250 Kbytes. If your snapshot image is too large, please try to zip it first before uploading.

Anyway, 25MB may not be a memory leak. 25MB is a small amount of memory, and it is possible the Java garbage collector does not bother to reclaim the memory, especially if your machine still have a lot of free memory.

The Java garbage collector may not aggresively reclaim memory if there is still a lot of free memory available, because reclaiming memory may waste CPU time and has no advantage. After a certain stage when the free memory become tight, the garbage collector may not aggregively reclaim memory. You may use System.gc() to force the garbage collector to reclaim memory.

Also, even if you are using an empty database, it does not mean the database will not use memory. As you are using the GUI, the GUI subsystem can also use memory.

To test for memory leak, I suggest you write a test program using hard coded data. Do not use any database. You may consider to start from the "Simple Bar Chart" sample code. Modify it to regenerate the chart in a loop and run as fast as it can (it should be able to achieve more than 10 charts per second). This can help to identify any leak quickly. If the memory usage does not grow indefinitely, there is no memory leak.

As a further test, you can insert "System.gc();" in the loop. In this way, the garbage collector will be forced to aggresively free up memory after each iteration.

If there is still memory leak, would you mind to attach the test program you are using (the one that is modified from the "Simple Bar Chart"), and also inform me of your Java brand, version and operating system. I will try to reproduce the problem.

Regards
Peter Kwan

  Re: makeImage() memory leak java
Posted by Greg B on Aug-31-2011 03:33
OK... Just to be clear 25MB in 20 minutes was all i allowed it to go on my last snapshot, it doesn't stop there, it would just keep growing indefinitely until it crashes with an out of memory error at my max heap number... now the 6MB over 10 hours is not nearly as much of a concern but with netbeans profiler i can force the garbage collection and take a snapshot... 3.5MB of that 6MB is orphaned objects in the makeImage() call.

The reason i run it against an empty database is so that i am not looking at it with huge arrays of numbers etc etc as i have many chartdirector graphs on the page.  If it grows and grows indefinitely with empty resutsets and a netbeans forced call to GC does not bring it back to the original starting used heap then objects are persisting.. I think i am right in these assumptions.  But i will look at what you suggested as well

  Re: makeImage() memory leak java
Posted by Peter Kwan on Aug-31-2011 12:57
Hi Greg,

It is normal that some objects are persisting in ChartDirector. They are mainly the font cache used by ChartDirector. It should not grow indefinitely because there is only a limited number of fonts in a computer, and charts typically only use a small number of fonts.

I have just done a simple test. I modified the "Simple Bar Chart" sample code to generate 10000 charts, like:

for (int i = 0; i < 10000; ++i)
{
    // Create a XYChart object of size 250 x 250 pixels
    XYChart c = new XYChart(250, 250);

    // Set the plotarea at (30, 20) and of size 200 x 200 pixels
    c.setPlotArea(30, 20, 200, 200);

    // Add a bar chart layer using the given data
    c.addBarLayer(data);

    // Set the labels on the x axis.
    c.xAxis().setLabels(labels);

    // Output the chart
    viewer.setImage(c.makeImage());

    //include tool tip for the chart
    viewer.setImageMap(c.getHTMLImageMap("clickable", "",
        "title='{xLabel}: US${value}K'"));
}

I run the sample code from the command line (use "java -cp ChartDirector.jar;. simplebar") and check the memory using the task manager. The memory usage never goes above 22MB in my case and stays at around 20MB. (The exact value depends on your Java brand, version, OS and PC configuration. Java will use more memory if your machine has more memory, but it should not increase indefinitely.)

I run the sample code from the command line to avoid the uncertainties introduced by the IDE and the profiler.

Regards
Peter Kwan