У меня есть самописное приложение Java - небольшой почтовый монитор. Он работает с базой данных MySQL, в которой есть таблица, которая заполняется где-то в другом месте. Он просматривает таблицу и отправляет письма, поскольку записи отображаются в таблице.Java: многопоточная почтовая программа утечки памяти
Моя проблема в том, что приложение утечки памяти. Я был совершенно уверен, что этого не произошло, поскольку объем всего, что я использую, кажется, исчезает, заставляя все объекты использовать сборщик мусора. Но через некоторое время (в зависимости от -Xmx I pass) приложение останавливается с ошибкой OutOfHeapSpace.
Я не могу опубликовать весь код, поскольку он больше не мой, но я попытался его воссоздать с помощью псевдокода.
Main:
Startup
Create .lock file (FileChannel)
Instantiate Main Class
Constructor Main:
Class.ForName for the MySQL driver
Read properties file (settings)
Create connection object (MySQL)
Fetch unsent mail ids (ArrayList)
while(true)
while have more mail ids
new Thread(Top Mail ID, MySQL Connection object, Sleep Time, Blacklist);
end while
if have no more mail ids in ArrayList:
sleep for a number of seconds (usually 300)
end if
end while
Constructor Thread:
Prepare Statement
New Thread(this).start();
Sleep
Thread run():
Select Record by passed Mail ID
Extract everything (Sender, Receiver, Subject etc.)
Check Blacklist, return if matched
Extract Attachments as blobs
То, что я пытался до сих пор:
jvisualvm показал мне, как изменения памяти с течением времени. То, что я вижу, - это зубчатая линия в куче: распределение и сбор памяти происходит регулярно, однако после коллекции всегда выделяется больше памяти, чем после последней коллекции. количество потоков кажется прекрасным, оно всегда падает до стандартного номера.
Сумма информации в jvisualvm для меня слишком велика. Там есть нити, которые я не могу определить, нити, которые я создаю, не перечислены как мой класс, поэтому трудно точно определить, что такое «мой» код.
Может ли кто-нибудь распознать какие-либо распространенные ошибки многопоточности в моем псевдокоде или рекомендовать какие-либо инструменты, которые позволят мне легче определить мои утечки?
спасибо.
Редактировать 1: Доступ к данным через объект соединения, который передается всем потокам, синхронизируется сам по себе.
Edit 2: Я проверил количество писем, которые unsendable (как эти пребывания в базе данных), существует около 10.
Редактировать 3: я нашел Eclipse, анализатор памяти, установил его, и он намекнул на проблема. Похоже, что использование PreparedStatements при сохранении одного объекта соединения сохраняет HashMap всех PreparedStatements, когда-либо выполняемых над этим соединением внутри него, поэтому добавляет все данные, когда-либо выбранные для него. Я полагался на PreparedStatement, выходящий из сферы действия и собираемый. Я переписал и попытаюсь, если это устранит проблему.
В таких случаях я бы хотя бы попытался найти FindBugs один раз. –
Я не знал этого инструмента. Установка сейчас. Спасибо. – 0xCAFEBABE