2015-04-09 5 views
0

У меня есть программа, которая загружает данные о запасах из Интернета, а затем создает фондовые объекты, содержащие метаданные запаса и массив исторических цен.сборщик мусора не работает

Сначала я наткнулся на более чем 20000 акций, создав их и ввел их в arraylist, чтобы записать их в db (все они в одной транзакции). это была не очень хорошая идея, и до того, как я закончил скачивать все акции, я хотел, чтобы программа умерла из-за OutOfMemory.

Затем я решил, что после каждых 500 акций, которые я добавляю в arraylist, я напишу их в БД и очистку arraylist (arraylist.clear() для GC, чтобы сделать его «волшебным»), а затем заполнить arraylist с еще одним новым 500 Акции и пройти через тот же процесс снова и снова.

Это тоже не сработало, и моя программа снова умерла из-за исключения OutOfMemory.

Я думал, что проблема может быть в некоторых местах в моем коде, и я сделал эксперимент и запустил один и тот же код, но одно небольшое различие: после создания каждого объекта запаса я не помещаю его в arraylist, и я просто продолжить и создавать фондовые объекты снова, не добавляя их в 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(); 
     } 
    } 
} 

Im добавляя больше информации:

Сток поля :

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; 
+0

Я предполагаю, что вы имеете в виду 'ArrayList.clear()' not 'ArrayList.clean()'. Вы не показываете, где в коде вы вызываете этот метод. – GriffeyDog

+0

Я исправил его. Я показал первую версию своего кода. Я отправлю второй. –

+0

Во-первых, этот код не показывает никакого разделения на 500 партий и очистки. Во-вторых, это не показывает, что происходит в жизненном цикле ArrayList. Между заполнением и очисткой он передается другим методам. Вам также нужно будет показать эти методы, чтобы убедиться, что все ссылки на данные очищены. Кроме того, что находится внутри акции? – RealSkeptic

ответ

1

Сначала я хотел бы начать с профилирования приложения с помощью инструмента, как JVisualVM (который поставляется вместе с JDK) и определять, что именно объекты сохраняются лишь в куче.

Во-вторых, нет метода 'clean()' на ArrayList, поэтому его непонятно, что вы на самом деле делали, чтобы предотвратить рост вашего списка на неопределенный срок.

Наконец, рассмотрите возможность установки условной точки останова в вашей программе, чтобы «поймать», когда список превышает ваши ожидания.

EDIT: Если вы спрашиваете сейчас:

«Может ли мой OutOfMemoryError быть связано с тем, что:

protected ArrayList<DailyData> _historicalData; 

растет и вносит свой вклад в давление памяти?'

Ответ на этот вопрос да. Вы также пытались увеличить память в своем процессе? Попробуйте запустить:

java -Xms1g -Xmx1g *yourProgram*

, чтобы увидеть, если он до сих пор не удается. У вас может не возникнуть утечка, возможно, просто ваше приложение нуждается в большем количестве памяти за то, что вы делаете.

+0

Я использовал его сейчас и увидел, что объект, который потребляет большую часть памяти, является объектом DailyData, каждый запас которого имеет около 1000 объектов DailyData. ohhhh Я просто подумал о причине, что очистить массив запасов будет недостаточно. Я думаю, я должен также очистить каждого из arraylist DailyData, что каждый отдельный запас имеет! Это правда??? –

+0

В вашем коде выше ничего не сказано о DailyData, поэтому мне неизвестно ... –

+0

Я добавил информацию –

Смежные вопросы