垃圾收集器不工作



我有一个程序,可以从互联网下载股票数据,然后创建一个包含股票元数据和历史价格数组的Stock对象。

起初,我运行了超过20000只股票,创建了它们,并将它们输入到一个数组列表中,以便将它们写入数据库(所有股票都在一笔交易中)。这不是一个好主意,在我下载完所有我想要的股票之前,这个程序因为内存不足而夭折了。

然后我决定,在我添加到arraylist的每500只股票之后,我会将它们写入DB,并清理arraylist(arraylist.clear()for GC,使其成为"魔术"),然后用另一只新的500只股票填充arraylist,并再次经历相同的过程。

这也不起作用,我的程序又因为内存不足异常而终止了。

我认为问题可能出现在我代码中的其他地方,我做了一个实验,运行了相同的代码,但有一点不同:在我创建每个Stock对象后,我不会将其放入arraylist,我只是继续并重新创建Stock对象,而不会将它们添加到arraylist中。

结果是,我的程序几乎没有消耗任何内存,这让我非常困惑和沮丧。

请帮我找出我的程序是否有问题

以下是一些代码行:

第一个版本:

ArrayList<Stock> stocksData = new ArrayList<Stock>();
Stock stock;
BufferedReader br = null;
String line = "";
try {
    br = new BufferedReader(new FileReader(YAHOO_STOCKS_SYMBOLS));
    while ((line = br.readLine()) != null) {
        String[] stockMetaData = line.split(CSV_SPLIT);
        stock = new Stock();
        if (stockMetaData.length >= 4) {
            stock.setSymbol(stockMetaData[0]);
            stock.setName(stockMetaData[1]);
            stock.setExchange(stockMetaData[2]);
            stock.setCategory(stockMetaData[3]);
            DATA_UPDATER.updateStockData(stock, fromDate, toDate);
            if (stock.getHistoricalData() != null
                    && stock.getHistoricalData().size() > 0) {
                stocksData.add(stock);
            }
        }
    }
}

第二个版本:

ArrayList<Stock> stocksData = new ArrayList<Stock>();
Stock stock;
BufferedReader br = null;
String line = "";
try {
    br = new BufferedReader(new FileReader(YAHOO_STOCKS_SYMBOLS));
    while ((line = br.readLine()) != null) {
        String[] stockMetaData = line.split(CSV_SPLIT);
        stock = new Stock();
        if (stockMetaData.length >= 4) {
            stock.setSymbol(stockMetaData[0]);
            stock.setName(stockMetaData[1]);
            stock.setExchange(stockMetaData[2]);
            stock.setCategory(stockMetaData[3]);
            DATA_UPDATER.updateStockData(stock, fromDate, toDate);
            if (stock.getHistoricalData() != null
                    && stock.getHistoricalData().size() > 0) {
                stocksData.add(stock);
            }
        }
        if (stocksData.size() == 500) {
            WritingUtils.getInstance().updateStocks(stocksData);
            stocksData.clear();
            // I also tried
            //System.gc();
        }
    }
}

我正在添加更多信息:

库存字段:

protected String _symbol;
protected String _name;
protected String _exchange;
protected Date _upToDate;
protected ArrayList<DailyData> _historicalData;

DailyData字段:

private Date _date;
private double _open;
private double _close;
private double _adjClose;
private double _high;
private double _low;
private double _volume;

首先,我将使用JVisualVM(JDK附带)这样的工具来分析应用程序,并精确定位堆中保留的对象。

其次,ArrayList上没有"clean()"方法,因此不清楚您实际做了什么来防止列表无限期增长。

最后,考虑在程序中设置一个条件断点,以便在列表增长超出预期时"捕获"。

编辑:如果你现在问的是:

"我的内存不足错误可能是因为以下事实吗:

protected ArrayList<DailyData> _historicalData;

是否在增长并导致记忆压力

答案是肯定的。你是否也尝试过增加你的过程的记忆?尝试运行:

java -Xms1g -Xmx1g *yourProgram*

看看它是否仍然失败。您可能没有泄漏,可能只是您的应用程序需要更多的内存来执行您正在执行的操作。

最新更新