我第一次使用JFreeChart,並使用TimeSeriesCollection()創建TimeSeriesChart。JFreeChart - Java堆空間問題
我的數據庫查詢reslutset是應用程序。造成1000條記錄。我正在使用org.jfree.date.time.Minute.Minute(int min .....)對象將其添加到TimeSeries對象。
我有一個JFrame,我可以直接添加ChartPanel。用戶將提供新的輸入參數並用新數據集重新加載圖表數據。因此,我通過調用下面的方法
dataset.removeAllSeries();
chart.removeLegend();
chart.getRenderingHints().clear();
cp.getChartRenderingInfo().setEntityCollection(null);
cp.removeAll();
cp.revalidate();
輸出是完美的清理每重裝之前。但我注意到,在Eclipse中多次運行該程序後,我看到下面有關Java堆空間的錯誤消息。有時候我也會在任務管理器中看到,即使數據集非常小(100條記錄),程序仍會在PC內存中佔據一席之地。
Exception occurred during event dispatching:
java.lang.OutOfMemoryError: Java heap space
at sun.util.calendar.Gregorian.newCalendarDate(Gregorian.java:67)
at java.util.GregorianCalendar.<init>(GregorianCalendar.java:575)
at java.util.Calendar.createCalendar(Calendar.java:1012)
at java.util.Calendar.getInstance(Calendar.java:964)
at org.jfree.chart.axis.DateTickUnit.addToDate(DateTickUnit.java:238)
at org.jfree.chart.axis.DateAxis.refreshTicksHorizontal(DateAxis.java:1685)
at org.jfree.chart.axis.DateAxis.refreshTicks(DateAxis.java:1556)
at org.jfree.chart.axis.ValueAxis.reserveSpace(ValueAxis.java:809)
at org.jfree.chart.plot.XYPlot.calculateDomainAxisSpace(XYPlot.java:3119)
at org.jfree.chart.plot.XYPlot.calculateAxisSpace(XYPlot.java:3077)
at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3220)
at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1237)
at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1677)
at javax.swing.JComponent.paint(JComponent.java:1029)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5124)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1491)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1422)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:294)
at javax.swing.RepaintManager.paint(RepaintManager.java:1225)
at javax.swing.JComponent._paintImmediately(JComponent.java:5072)
at javax.swing.JComponent.paintImmediately(JComponent.java:4882)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:786)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:694)
at javax.swing.RepaintManager.access$700(RepaintManager.java:41)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1636)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:646)
at java.awt.EventQueue.access$000(EventQueue.java:84)
at java.awt.EventQueue$1.run(EventQueue.java:607)
at java.awt.EventQueue$1.run(EventQueue.java:605)
at java.security.AccessController.doPrivileged(Native Method)
我的應用程序如下:
我有一個JFrame上,我直接傳遞一個表給它之後添加ChartPanel。
chart = ChartFactory.createTimeSeriesChart("Peak monitor", , "Time: Zoom in", "# of Requests Logged", createDataset(from,to), true, false, false);
chartpanel = new ChartPanel(chart);
FramePanel.this.add(cp);
validate();
這裏createDataset(從,到)是一種方法
private TimeSeriesCollection createDataset(Date from, Date to) {
dataset.addSeries(controller.getStuff(from, to));
return dataset;
}
getStuff被稱爲的SwingWorker線程內(DIBkgd法)
public TimeSeries getStuff(Date from, Date to) {
s1 = new TimeSeries("Log Requests");
final Date from1 = from;
final Date to1 = to;
progressDialog.setVisible(true);
sw = new SwingWorker<Void, Integer>() {
@Override
protected Void doInBackground() throws Exception {
if (db.getCon() == null) {
db.connect();
}
Arrlst2.clear();
Arrlst2= db.getDataDB(from1, to1);
for (Qryobjects x : Arrlst2) {
s1.add(new Minute(x.getMinute(), x.getHour(), x.getDay(), x.getMonth(), x.getYear()), x.getCount());
}
System.out.println("finished fetching data");
return null;
}
@Override
protected void done() {
progressDialog.setVisible(false);
}
};
sw.execute();
return s1;
}
在我的數據庫類執行getDataDB:
public List<Qryobjects> getDataDB(Date from, Date to) {
PreparedStatement select;
ResultSet rs;
String selectSql = "Select Sum(Cnt) Cid, Hr, Min, Dat from (Select count(H.Request_Id) Cnt , To_Char(H.Timestamp,'HH24') HR, To_Char(H.Timestamp,'mm') MIN, To_Char(H.Timestamp,'MM-dd-yyyy') DAT From Status_History H Where H.Timestamp Between ? And ? Group By H.Request_Id, H.Timestamp Order By H.Timestamp Asc) Group By Hr, Min, Dat order by Dat asc";
try {
select = con.prepareStatement(selectSql);
select.setDate(1, from);
select.setDate(2, to);
rs = select.executeQuery();
System.setProperty("true", "true");
while (rs.next()) {
int cnt = rs.getInt("cid");
int hour = Integer.parseInt(rs.getString("Hr"));
int min = Integer.parseInt(rs.getString("Min"));
int month = Integer.parseInt(rs.getString("dat").substring(0, 2));
int day = Integer.parseInt(rs.getString("dat").substring(3, 5));
int year = Integer.parseInt(rs.getString("dat").substring(6, 10));
Arrlst1.add(new Qryobjects(cnt, hour, min, day, month,year));
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
return Arrlst1;
}
它可能只是不給java足夠的負載所有的數據。嘗試用-Xmx1024m – radai 2013-03-08 17:32:19
我懷疑,要麼你的代碼,或在JFreeChart的一些代碼不釋放其產生的所有它的引用中的對象被錨定在內存,即使你期待他們GC'd運行。經過幾個週期後,您的相當小的數據集將填充可用的堆併產生OutOfMemoryError。 Java分析器應該幫助確定什麼是消耗內存來幫助您進行調試。 [VisualVM](http://docs.oracle.com/javase/6/docs/technotes/guides/visualvm/)包含在JDK中,可以幫助您收集這些信息。 – 2013-03-08 17:39:05
使用探查器找出泄漏。注意'靜態'變量,如果有的話。 – 2013-03-08 18:19:45