Hi we are new to JFreeChart,
We are using JFreeChart for showing bar chart inside Table cell using chartPanel in TableCell Renderer class in our Java swing application. Our requirement is to update the chart for every four seconds for minimum of 100 rows. Here we are facing memory leackage issue. The heap memory is growing linearly. Help us out to solve this issue.
We are using JFreeChart 1.0.19 version.
Thanks,
4W Support.
Memory Leak issue
-
- Posts: 7
- Joined: Mon Jan 14, 2019 3:17 pm
- antibot: No, of course not.
-
- Posts: 513
- Joined: Wed Sep 12, 2007 3:18 pm
Re: Memory Leak issue
Several strategies are examined here.
-
- Posts: 7
- Joined: Mon Jan 14, 2019 3:17 pm
- antibot: No, of course not.
Re: Memory Leak issue
Thanks For your response...
The Link you referred is not related to our scenario. Here we attach a code snippet which explain our exact scenario.
In this scenario the Heap memory is linearly increases up-to 1 GB and so on , without the renderer call heap memory is stable at 20MB.
can you please advice on this scenario.
The Link you referred is not related to our scenario. Here we attach a code snippet which explain our exact scenario.
In this scenario the Heap memory is linearly increases up-to 1 GB and so on , without the renderer call heap memory is stable at 20MB.
can you please advice on this scenario.
Code: Select all
Class ThreadSample Extends Thread{
@Override
public void run() {
do{
function();
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while(true);
}
function(){
for (int i = 0; i < 100; i++) { //100 is minimum row count this might be more than 600.
for (int j = 0; j < 20; j++) {
/*
*Here mainClass.Table is an static JTable from main class.
*/
if(mainClass.Table.getTableHeader().getColumnModel().getColumn(j).getHeaderValue().toString().contains("graph"){
TableCellRenderer tr = new GraphCellRenderer(i,j);
mainClass.Table.getColumnModel().getColumn(j).setCellRenderer(tr);
}
}
}
}
}
class GraphCellRenderer implements TableCellRenderer {
public static String[] time = { "10", "20", "30", "40", "50", "60", "70", "80", "90", "100", "110", "120", "130",
"140", "150", "160", "170", "180", "190", "200" };
public static DefaultCategoryDataset gData = new DefaultCategoryDataset();
public static int row, col;
public static int maxLimit=100;
static int rowValue;
GraphCellRenderer(int rowdummy, int column) {
row = rowdummy;
col = column;
//System.out.println("column" + column + "row" + row);
}
@SuppressWarnings("unused")
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row2, int column) {
rowValue=row2;
JFreeChart chart = null;
ChartPanel chartPanel = null;
CategoryPlot plot = null;
for(int i=0;i<row;i++) {
if (i==row2) {
chart = ChartFactory.createBarChart("", "", "", getData(row2, column), PlotOrientation.VERTICAL,false, false, true);
chartPanel = new ChartPanel(chart);
plot = (CategoryPlot) chart.getPlot();
chart = null;
plot.setBackgroundPaint(Color.white);
plot.setOutlinePaint(null);
plot.getDomainAxis().setCategoryMargin(0.08);
BarRenderer renderer = (BarRenderer) plot.getRenderer();
CategoryItemRenderer renderer1 = new CustomRenderer(
new Paint[] { Color.red, Color.magenta, Color.green,
Color.red, Color.magenta, Color.magenta,
Color.green, Color.red, Color.magenta,
Color.red, Color.green, Color.red, Color.magenta,
Color.green, Color.red, Color.magenta,
Color.magenta, Color.green, Color.red ,Color.red});
plot.setRenderer(renderer1);
renderer1 = null;
CategoryAxis numberaxis = (CategoryAxis) plot.getDomainAxis();
numberaxis.setVisible(false);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setRange(0, maxLimit);
rangeAxis.setVisible(false);
rangeAxis.setTickMarksVisible(false);
ValueMarker Normal = new ValueMarker(300);
Normal.setPaint(Color.GREEN);
final IntervalMarker target = new IntervalMarker(50.0, 60.0);
final IntervalMarker target1 = new IntervalMarker(70.0, 80.0);
final IntervalMarker target2 = new IntervalMarker(80.0, 90.0);
return chartPanel;
}
}
return null;
}
public static DefaultCategoryDataset getData(int row2, int column) {
for (int ii = 0; ii <= row; ii++) {
if (row2 == ii) {
gData.clear();
for (int i = 0; i < 20; i++) {
if (i==0){
/*
*mainClass.value is an int[] array from another class.
*which has values of each bar.
*/
int mLim=mainClass.value[row2][i];
if (mLim!=0)
maxLimit=mLim;
continue;
}
gData.addValue(mainClass.value[row2][i], "", time[i-1]);
}
return gData;
}
}
return null;
}
}
class CustomRenderer extends BarRenderer {
private static final long serialVersionUID = 1L;
private Paint[] colors;
public CustomRenderer(Paint[] colors) {
for (int i=0;i<20;i++){
if(mainClass.dummyColor[GraphCellRenderer.rowValue][i]!=null) {
try {
/*
*mainClass.dummyColor[][] is an static Paint[][] array from another class
* which has color values of each bar
*/
colors[i]=mainClass.dummyColor[GraphCellRenderer.rowValue][i];
}catch(Exception e){
e.printStackTrace();
}
}
}
this.colors = colors;
}
public Paint getItemPaint(final int row, final int column) {
return this.colors[column % this.colors.length];
}
}
-
- Posts: 513
- Joined: Wed Sep 12, 2007 3:18 pm
Re: Memory Leak issue
Your fragment is incorrectly synchronized: it updates a GUI component from a thread other than the event dispatch thread; the approach shown here may be appropriate. In addition, it is unclear why the TableCellRenderer is re-creating the entire chart with each invocation. Each chart should be created once during initialization; each chart's dataset should be updated only on the event dispatch thread; and the TableCellRenderer should return only the chart panel for the row and column specified in the implementation's signature.