我有一个自己写的Java应用程序 - 一个小邮件监视器。它可以与MySQL数据库一起工作,该数据库有一个定期填充到别处的表。它会查看表格,并在记录出现在表格中时发送邮件。Java:多线程邮件应用程序泄漏内存
我的问题是,应用程序泄漏内存。我确信它没有,因为我使用的所有东西的范围似乎都消失了,使得所有使用垃圾的对象都可以收集。但过了一段时间(取决于-Xmx通过),应用程序停止并出现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:通过传递给所有线程的连接对象的数据访问本身是同步的。
编辑2:我检查是不可发送的邮件的数目(如这些停留在数据库中),大约有10
编辑3:我发现的Eclipse内存分析器,安装它,它暗示在问题。看起来,在保留一个连接对象的同时使用PreparedStatements使所有PreparedStatements的HashMap始终通过此连接运行,从而将添加的所有数据添加到它。我依靠PreparedStatement超出范围并被收集。如果这能解决问题,我会重写并尝试。
在这种情况下,我至少会尝试一次FindBugs。 –
我不知道那个工具。现在安装。谢谢。 – 0xCAFEBABE