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

标签 java hibernate jakarta-mail quartz-scheduler out-of-memory

我有一个在 Tomcat 6 上运行的 Web 应用程序,该应用程序是我使用 Netbeans 6.9.1 及其用于实体类和持久性的向导创建的。它使用 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>

使用 Quartz 创建的任务每 15 分钟运行一次,使用 JavaMail(使用 IMAP)检查 GMail 帐户,检索所有消息,处理它们(查找一些信息)并使用 Hibernate 将包含该信息的对象存储到数据库中。然后它将所有邮件标记为已删除,因此下次运行时不会处理它们。

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

为了尝试不同的解决方案,我多次更改了 -Xms -Xmx 和 PermGem Size,但总是达到系统停止工作且内存未释放的程度。

知道我可以从哪里开始寻找这个问题吗?我已经为 Java VM 分配了超过 1.5GBytes,即使它持续了一天多,它也挂起。

当 Tomcat 和所有应用程序停止工作时,没有堆栈跟踪。

谢谢

最佳答案

在 JDK 中附加 jvisualvm 以获取内存分析。

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

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

如果您不断收到 OOM 异常,请考虑在单独的 JVM 中运行邮件发送,这样它就不会影响应用程序的其余部分。

关于使用 Hibernate、Quartz 和 JavaMail 的应用程序中的 Java OutOfMemory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6612778/

相关文章:

java - 为什么 Java 的 "protected"的保护程度低于默认值?

java - 使用 FieldInterceptor 问题的 Hibernate OneToOne 延迟加载

java - 无法找到命名参数

java - 如何测试 Spring 的 JavaMailSender

java - 添加按键和鼠标监听器

java - Java 和 Arduino 进程共享串口

java - 如何用java读取网站源代码

hibernate - 使用 @OneToOne 和 @OneToMany 时如何进行 Hibernate OUTER JOIN

java - 这段代码有什么问题。运行时错误

JavaMail smtp 属性(用于 STARTTLS)