Hi,
I am using JFreeChart in an application and found the following problem..
Test Environment : Win2K, JDK1.3.1
JFreeChart 0.9.4 , JCommon 0.7.1
I am simulating a Monitor Panel with SwingWorker class.. Found memory usage is keep on increasing.. till I get OutOfMemory error..
Test files attached here with...
Any suggestions.......??
Thanks in advance...
-----------------------------------------------------------------
MonitorFrame.java
-----------------------------------------------------------------
package testmemory;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JFrame;
public class MonitorFrame
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Monitor Panel");
MyChartPanel panel = new MyChartPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.setSize(800, 800);
frame.setVisible(true);
frame.pack();
}
}
-------------------------------------------------------------------
MyChartPanel.java
-------------------------------------------------------------------
package testmemory;
import java.util.Date;
import java.awt.*;
import javax.swing.*;
import com.jrefinery.chart.*;
import com.jrefinery.data.*;
public class MyChartPanel extends JPanel
{
private JPanel mainPnl = new JPanel(new GridLayout(3, 3, 5, 5));
private ChartPanel[] cpanel = new ChartPanel[9];
private JFreeChart[] charts = new JFreeChart[9];
private XYDataset[] dsets = new XYDataset[9];
private BasicTimeSeries[] series = new BasicTimeSeries[9];
private TimeSeriesCollection[] coll = new TimeSeriesCollection[9];
private SwingWorker worker = null;
private boolean active = true;
private int counter= 0;
public MyChartPanel()
{
for(int x=0; x< 9; x++)
{
series[x] = new BasicTimeSeries("Series"+x, Millisecond.class);
coll[x] = new TimeSeriesCollection();
coll[x].addSeries(series[x]);
dsets[x] = coll[x];
charts[x] = ChartFactory.createTimeSeriesChart("Chart "+x,"","",dsets[x],true);
cpanel[x] = new ChartPanel(charts[x]);
cpanel[x].setPreferredSize(new Dimension(250, 200));
mainPnl.add(cpanel[x]);
}
this.add(mainPnl, BorderLayout.CENTER);
worker = new SwingWorker()
{
public Object construct()
{
return startWorker();
}
};
worker.start();
}
private Object startWorker()
{
while(active)
{
try
{
updateChartDatasets();
updateMonitorCharts();
if (Thread.interrupted())
{
throw new InterruptedException();
}
Thread.sleep((long)2000);
counter++;
}
catch(Exception exp)
{
exp.printStackTrace();
}
}
return "Done";
}
private void updateChartDatasets()
{
Date currTime = new Date();
double value = Math.random();
for(int x=0; x<9; x++)
updateSeries(series[x], currTime, value);
}
private void updateSeries(BasicTimeSeries series, Date time, double value)
{
if(counter > 20)
series.delete(series.getTimePeriod(0));
series.add(new Millisecond(time), new Double(value));
}
private void updateMonitorCharts()
{
try
{
Runnable doUpdateTime = new Runnable()
{
public void run()
{
for(int x=0; x<9; x++)
charts[x].getXYPlot().setDataset(dsets[x]);
}
};
SwingUtilities.invokeAndWait(doUpdateTime);
}
catch(Exception exp)
{
exp.printStackTrace();
}
}
}
--------------------------------------------------------------
SwingWorker.java
--------------------------------------------------------------
package testmemory;
import javax.swing.SwingUtilities;
public abstract class SwingWorker
{
private Object value = null;
private Thread thread = null;
/**
* Class to maintain reference to current worker thread
* under separate synchronization control.
*/
private static class ThreadVar
{
private Thread thread;
ThreadVar(Thread t) { thread = t; }
synchronized Thread get() { return thread; }
synchronized void clear() { thread = null; }
}
private ThreadVar threadVar;
/**
* Get the value produced by the worker thread, or null if it
* hasn't been constructed yet.
*/
protected synchronized Object getValue()
{
return value;
}
/**
* Set the value produced by worker thread
*/
private synchronized void setValue(Object x)
{
value = x;
}
/**
* Compute the value to be returned by the <code>get</code> method.
*/
public abstract Object construct();
/**
* Called on the event dispatching thread (not on the worker thread)
* after the <code>construct</code> method has returned.
*/
public void finished() { }
/**
* A new method that interrupts the worker thread. Call this method
* to force the worker to stop what it's doing.
*/
public void interrupt()
{
Thread t = threadVar.get();
if (t != null) {
t.interrupt();
}
threadVar.clear();
}
public void join() throws InterruptedException
{
Thread t = threadVar.get();
if(t != null)
{
t.join();
}
}
/**
* Return the value created by the <code>construct</code> method.
* Returns null if either the constructing thread or the current
* thread was interrupted before a value was produced.
*
* @return the value created by the <code>construct</code> method
*/
public Object get()
{
while (true)
{
Thread t = threadVar.get();
if (t == null)
{
return getValue();
}
try
{
t.join();
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt(); // propagate
return null;
}
}
}
/**
* Start a thread that will call the <code>construct</code> method
* and then exit.
*/
public SwingWorker()
{
final Runnable doFinished = new Runnable()
{
public void run() { finished(); }
};
Runnable doConstruct = new Runnable()
{
public void run()
{
try
{
setValue(construct());
}
finally
{
threadVar.clear();
}
SwingUtilities.invokeLater(doFinished);
}
};
Thread t = new Thread(doConstruct);
threadVar = new ThreadVar(t);
}
/**
* Start the worker thread.
*/
public void start()
{
Thread t = threadVar.get();
if (t != null)
{
t.start();
}
}
}
------------------------------------------------------------------------
Dynamic Chart [ Memory problem... ]
Re: Dynamic Chart [ Memory problem... ]
Hi Reji,
I'm running your test code now. In MyChartPanel.java I've changed the code slightly. updateMonitorCharts() is redundant, since changing the series refreshes the charts anyway. And I added a line to print out the current memory stats...and also reduced the sleep time to 200, to speed things up:
private Object startWorker() {
while (active) {
try {
updateChartDatasets();
// *** CHANGE ***
//updateMonitorCharts();
System.out.println(Runtime.getRuntime().freeMemory()+"/"
+Runtime.getRuntime().totalMemory());
// *** CHANGE ***
if (Thread.interrupted()) {
throw new InterruptedException();
}
Thread.sleep((long) 200);
counter++;
} catch (Exception exp) {
exp.printStackTrace();
}
}
return "Done";
}
So far, the code is running fine for me on JDK1.3 and Linux. I'll leave it running overnight and see what happens.
Regards,
DG
I'm running your test code now. In MyChartPanel.java I've changed the code slightly. updateMonitorCharts() is redundant, since changing the series refreshes the charts anyway. And I added a line to print out the current memory stats...and also reduced the sleep time to 200, to speed things up:
private Object startWorker() {
while (active) {
try {
updateChartDatasets();
// *** CHANGE ***
//updateMonitorCharts();
System.out.println(Runtime.getRuntime().freeMemory()+"/"
+Runtime.getRuntime().totalMemory());
// *** CHANGE ***
if (Thread.interrupted()) {
throw new InterruptedException();
}
Thread.sleep((long) 200);
counter++;
} catch (Exception exp) {
exp.printStackTrace();
}
}
return "Done";
}
So far, the code is running fine for me on JDK1.3 and Linux. I'll leave it running overnight and see what happens.
Regards,
DG
Re: Dynamic Chart [ Memory problem... ]
Still running OK this morning. Can you try a different JDK and see if that makes a difference...
Regards,
DG
Regards,
DG
Re: Dynamic Chart [ Memory problem... ]
Hi,
I found another thing.. Memory is keep on adding while I am calling Thread.sleep() at the rate of 100KB per 1 second sleep time. Why is it so?
Any idea...?
I have modified the method like this to print the memory usage (KB) before and after Thread.sleep()...
-----------------------------------------------------------------------
private Object startWorker()
{
while(active)
{
try
{
System.out.println("-------------------");
updateChartDatasets();
printMemoryUsage();
if (Thread.interrupted())
{
throw new InterruptedException();
}
Thread.sleep((long)2000);
printMemoryUsage();
counter++;
}
catch(Exception exp)
{
exp.printStackTrace();
}
}
return "Done";
}
private void printMemoryUsage()
{
System.out.println( (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024 );
}
-------------------------------------------------------------------------
regards
reji
I found another thing.. Memory is keep on adding while I am calling Thread.sleep() at the rate of 100KB per 1 second sleep time. Why is it so?
Any idea...?
I have modified the method like this to print the memory usage (KB) before and after Thread.sleep()...
-----------------------------------------------------------------------
private Object startWorker()
{
while(active)
{
try
{
System.out.println("-------------------");
updateChartDatasets();
printMemoryUsage();
if (Thread.interrupted())
{
throw new InterruptedException();
}
Thread.sleep((long)2000);
printMemoryUsage();
counter++;
}
catch(Exception exp)
{
exp.printStackTrace();
}
}
return "Done";
}
private void printMemoryUsage()
{
System.out.println( (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024 );
}
-------------------------------------------------------------------------
regards
reji