我有一个程序,可以从互联网下载股票数据,然后创建一个包含股票元数据和历史价格数组的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*
看看它是否仍然失败。您可能没有泄漏,可能只是您的应用程序需要更多的内存来执行您正在执行的操作。