使用Hibernate、Quartz和JavaMail的应用程序中的Java OutOfMemory

使用Hibernate、Quartz和JavaMail的应用程序中的Java OutOfMemory,java,hibernate,jakarta-mail,quartz-scheduler,out-of-memory,Java,Hibernate,Jakarta Mail,Quartz Scheduler,Out Of Memory,我有一个运行在Tomcat6上的web应用程序,它是我用NetBeans6.9.1及其Wizzard创建的,用于实体类和持久性。它使用Hibernate、MySQL作为数据库、Quartz每15分钟运行一次任务以及JavaMail hibernate配置如下所示: <?xml version="1.0" encoding="UTF-8" ?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persi

我有一个运行在Tomcat6上的web应用程序,它是我用NetBeans6.9.1及其Wizzard创建的,用于实体类和持久性。它使用Hibernate、MySQL作为数据库、Quartz每15分钟运行一次任务以及JavaMail

hibernate配置如下所示:

<?xml version="1.0" encoding="UTF-8" ?> 
 <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
 <persistence-unit name="GVPU" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.ejb.HibernatePersistence</provider> 
  <class>com.test.MyfirstEntity</class> 
  <class>com.test.MySecondEntity</class> 
  <exclude-unlisted-classes>true</exclude-unlisted-classes> 
 <properties>
  <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> 
  <property name="hibernate.connection.username" value="root" /> 
  <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> 
  <property name="hibernate.connection.password" value="password" /> 
  <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/db" /> 
  <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider" /> 
  <property name="hibernate.hbm2ddl.auto" value="update" /> 
  <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" /> 
  <property name="hibernate.c3p0.acquire_increment" value="1" /> 
  <property name="hibernate.c3p0.idle_test_period" value="300" /> 
  <property name="hibernate.c3p0.timeout" value="100" /> 
  <property name="hibernate.c3p0.max_size" value="100" /> 
  <property name="hibernate.c3p0.min_size" value="0" /> 
  <property name="hibernate.c3p0.max_statements" value="0" /> 
  </properties>
  </persistence-unit>
  </persistence>

org.hibernate.ejb.HibernatePersistence
com.test.MyfirstEntity
com.test.MySecondEntity
真的
使用Quartz创建的任务每15分钟运行一次,使用JavaMail(使用IMAP)检查GMail帐户,检索所有消息,处理它们(查找一些信息),并使用Hibernate将包含这些信息的对象存储到数据库中。然后它会将所有邮件标记为已删除,这样下次运行时它们就不会被处理

每次运行此任务时,它都会消耗10、20、50字节,具体取决于它处理的邮件数量。我看过MySQL管理员,数据库连接在不需要时关闭。但是如果我查看进程内存(在它运行的linux机器中),内存会一直增长,直到达到CPU使用率为100%的极限,Tomcat不再响应

为了尝试不同的解决方案,我已经多次更改了-Xms-Xmx和PermGem大小,但是它总是达到系统停止工作并且内存没有被释放的点

你知道我从哪里开始寻找这个问题吗?我已经为Java虚拟机分配了超过1.5GBytes的内存,而且它也会挂起,即使它会持续一天以上

当Tomcat和所有应用程序停止工作时,没有stacktrace


感谢一般方法:获取内存转储,查找数量最多的对象或最大的对象,看看它们是否不应该存在,但仍然存在。然后,您可以查看哪些对象阻止收集此垃圾(通过保存垃圾的引用)。

在JDK中使用jvisualvm进行连接,以获取内存分析

请注意,据我所知,JavaMail不能有效地处理大型附件,因此产生的邮件会变得更大。因此,在处理下一封邮件之前,必须确保邮件已从内存中清除

我建议您设置一个本地SMTP服务器——这对于大多数Linux发行版来说非常简单——并让您的Java应用程序与之对话。这将使您的任务更快地完成,然后释放内存


如果您继续获得OOM异常,那么考虑将邮件运行在单独的JVM中,这样它不会影响您的应用程序的其余部分。

< P>您如何管理进程运行之间的休眠会话?是否确实没有将进程以前所有运行的所有缓存对象保留在Hibernate会话缓存或您自己的缓存中?

您可能没有正确关闭数据库连接。这可能会导致对象保留在内存中,而不会被垃圾回收。检查放弃的连接并记录它们(在c3p0配置中)。我曾经遇到过类似的问题,最终归结为恶意数据库连接