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

发布于 2024-11-19 02:11:13 字数 2543 浏览 8 评论 0原文

我有一个在 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 和所有应用程序停止工作时,就没有堆栈跟踪。

谢谢

I have a web application running on Tomcat 6, that I created with Netbeans 6.9.1 and its wizzards for Entity classes and persistence. It uses Hibernate, MySQL as database, Quartz for running a task every 15 minutes, and JavaMail.

The hibernate configuration is as follows:

<?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>

The task created with Quartz, that runs every 15 minutes, checks a GMail account using JavaMail (with IMAP), retrieves all the messages, process them (looks for some info) and store objects with that information into the DB using Hibernate. Then it mark all mails as deleted, so they are not process on the next run.

Everytime this task runs, it consumes 10, 20, 50MBytes depending on how many mails it process. I have looked at MySQL Administrator, and the DB connections are closed when not needed. But if I look at the process memory (in the linux machine it runs) the memory grows until it reach a limit where the CPU usage is 100%, and Tomcat does not responds any more.

I have changed several times -Xms -Xmx and PermGem Size in order to try different solutions, but it always reaches a point where the system stops working and the memory is not been released.

Any idea where I can start looking for this problem? I have assigned more that 1.5GBytes to the Java VM, and it also hangs even though it last more than a day.

When Tomcat and all the application stops working, there is no stacktrace.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

执手闯天涯 2024-11-26 02:11:13

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

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

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

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

Attach with jvisualvm in the JDK to get a memory profiling.

Note that to my knowledge JavaMail does not handle large attachments efficiently, and the resulting mails get even larger. Hence you must make certain that the mail is cleared from memory before the next is being processed.

I would suggest that you set up a local SMTP server - this is very easy with most Linux distributions - and let your Java application talk to that instead. This will make your task finish much faster and then release the memory.

If you keep getting OOM exceptions then consider running the mail sending in a separate JVM so it does not influence the rest of your application.

我爱人 2024-11-26 02:11:13

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

General approach: get memory dump and look for most numerous objects or biggest objects and see if they should not exist, but still are. Then you can see what objects preventing this garbage from being collected (via holding references to the garbage).

戏蝶舞 2024-11-26 02:11:13

如何管理进程运行之间的 Hibernate 会话?您确定没有将进程所有先前运行的所有缓存对象保留在 Hibernate 会话缓存或您自己的缓存中吗?

How do you manage Hibernate sessions between the process runs? Are you sure you are not keeping all cached objects from all previous runs of your process in the Hibernate session cache or in your own cache?

°如果伤别离去 2024-11-26 02:11:13

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

You might not be closing the database connections properly. This may cause the objects to remain in the memory and not get garbage collected. Check for abandoned connections and log them (in your c3p0 configurations). I once ran into a similar issue and it boiled downed to rogue database connections.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文