JFreeChart-Java堆空间问题 [英] JFreeChart - Java Heap Space issue

查看:57
本文介绍了JFreeChart-Java堆空间问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是第一次使用JFreeChart,并且正在使用TimeSeriesCollection()创建一个TimeSeriesChart.

I am using JFreeChart for the first time and I am using a TimeSeriesCollection() to create a TimeSeriesChart.

我从数据库查询中得到的结果集是app.约有1000条记录.我正在使用 org.jfree.date.time.Minute.Minute(int min ...)对象将其添加到TimeSeries对象.

My reslutset from the DB query is app. aroung 1000 records. I am using org.jfree.date.time.Minute.Minute(int min.....) object to add it to a TimeSeries object.

我有一个JFrame,可以直接在其上添加ChartPanel.用户将提供新的输入参数,并使用新的数据集重新加载图表数据.因此,我会在每次重新加载之前通过在方法中调用以下内容进行清理

I have a JFrame on which I add the ChartPanel directly. The user will provide new input parameters and reload the chart data with new dataset. So I clean up before every reload by calling the following in a method

            dataset.removeAllSeries();
            chart.removeLegend();
            chart.getRenderingHints().clear();
            cp.getChartRenderingInfo().setEntityCollection(null);
            cp.removeAll();
            cp.revalidate();

输出是完美的.但是我注意到,在多次在Eclipse中"运行该程序后,我看到以下有关Java堆空间的错误消息.有时,即使数据集很小(100条记录),我也可以在任务管理器中看到程序会占用PC内存.

The output is perfect. But I noticed that after running the program 'several times in Eclipse' I see the below error message about Java heap space. Sometimes I also see in the Task Manager that the program hogs on the PC memory even though the dataset is very small (100 records).

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.

I have a JFrame on which I directly add the ChartPanel after passing a Chart to it.

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(from,to)是一种方法

 private TimeSeriesCollection createDataset(Date from, Date to) {
    dataset.addSeries(controller.getStuff(from, to));
    return dataset;
}

在SwingWorker线程(DIBkgd方法)中调用

getStuff

getStuff is called within a SwingWorker thread (DIBkgd method)

 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 :

Within my Database class the getDataDB is executed:

 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;
}

推荐答案

我解决了我的问题.

我从@TrashGod那里得到了使用dispose()的线索.但这对我不直接有效.

I took the clue from @TrashGod to use dispose(). But it does not work directly for me.

我将图表面板直接添加到我的主要JFrame容器中.就我而言,我想一遍又一遍地在同一JFrame容器中创建图表.

I was adding the chart panel directly to my main JFrame container. And in my case, I wanted to keep creating the charts in the same JFrame container over and over.

我首先尝试清除数据集,并在图表面板上调用了removeall(),但这没有帮助.

I first tried clearing the dataset and called removeall() on the chart panel, but it did not help.

然后,我找到的解决方案是创建另一个JFrame并向其中添加图表面板.当我关闭此JFrame时,我再次清除数据集,并在图表面板上调用removeall(),也称为dispose().因此,每次创建一个新图表时,都会创建此JFrame及其子组件,并在退出该JFrame时将其完全废弃.

Then the solution I found was to create another JFrame and add the chart panel to it. And when I closed this JFrame, I again clear the dataset and called removeall() on the chart panel and also called dispose(). So everytime, I create a new chart, this JFrame and its children componenets are created and are completely disposed when I exit this JFrame.

因此,当创建图表时,将创建一个新的JFrame,然后对其进行处理.

So, when a chart is created a new JFrame is created and then disposed.

我还应该补充一点,在进行了此更改之后,我开始在Java VisualVM Profiler中看到锯齿"模式.我还使用了Jprofiler,当我在运行程序时看到超过100,000个对象被创建时,我感到震惊.现在,我看到创建了9000个对象,并且对于JFree包来说,它保持不变,并根据检索到的结果集,数据库包中的对象数量增加或减少.

I should also add that after making this change I started to see the Saw Tooth pattern in the Java VisualVM profiler. I also used Jprofiler and I was shocked to see more than 100,000 objects were created while I was running my program. Now, I see 9000 objects created and it remains constant for the JFree package and based on my resultset retrieved the number of objects in my database package increases or decreases.

我要做的另一件事是使我的SQL进行解析并将其转换为数字.我想减少创建的对象数量,并且还减少程序对每个检索到的记录进行的处理.

One more thing I did was to make my SQL do the parsing and convert it to a number. I wanted to reduce the number of objects created and also reduce the processing done by my program for each retrieved record.

这篇关于JFreeChart-Java堆空间问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆