6

我已经用Java制作了MVC webapp,但是当我每天运行一次它时,由于内存错误,它再次关闭。

这个错误是这样的:线程“http-apr-12136-exec-42”中的异常java.lang.OutOfMemoryError:Java堆空间

java.sql.SQLException: java.lang.OutOfMemoryError: Java 堆空间

我有带有崩溃统计信息的 hprof,其中具体是如何使用内存的。如果我使用 Eclipse Memory Analizer 打开 hprof,我会得到以下结果:

在 rar 中:https ://mega.co.nz/#!Ht41xJDJ!MooePBSv5yOYSNN5OuvF7Afn2rcN-KJ2tXGSsgqtsaI

或在文件夹中:https ://mega.co.nz/#F!6hJUyKbQ!D_Kb23E3KfAJqcd5EeAt0A

在概览报告中,我有这张图 (OverviewEMA.JPG):我不知道这张图在说什么……我不明白。

在第二个选项卡,默认报告中,我有这个图形(DefaulReport_EMA.JPG):它说问题可能是“org.hibernate.internal.SessionFactoryImpl”的一个实例。但我不知道如何解决该实例。

在下一个选项卡中。在支配树中,再次出现前一个实例,它使用大约 42MB 的内存(与显示第一张图相同)。图像是 DominatorTree_EMA.JPG

如果我展开第一个类(给出问题的类),我有这个图形(DominatorTreeExpanded_EMA.JPG):

在下一个选项卡中,在直方图中,图形是这样的 (Histogram_EMA.JPG):

在 Unreachable objects 中,结果是这样的(UnreachableObjects_EMA.JPG):

最后两张图我不太明白

最后,我还有 Java VisualVM 的报告,我有这个结果(Heapdump_JVM.JPG):

根据该图,除了 Integer 和 String 对象之外,HashMap 对象是问题所在。我认为的 Hashmap 对象是类发送到 jsp 文件的模型对象,它从 JPA 对象(Hibernate 的对象)开始,所以问题可能是这样,但我不知道如何解决它...

有人可以帮助我吗?有人知道我该如何解决吗?您需要更多信息吗?

谢谢!

4

3 回答 3

4

在查看 DominatorTree_Expanded 时,您似乎在重复创建 SessionFactory(内存中有 144 个)。这应该只在启动时创建一次,然后用于创建任意数量的会话。

另请参阅下面关于正确使用 Hibernate Session 的评论。


您的 Hibernate 会话应该是请求的本地会话- 并在请求结束时关闭。您可以在控制器处理和视图 (JSP) 呈现期间使用“OpenSessionInView”模式将会话绑定到线程。

我怀疑,由于您要使用 OutOfMemory,因此您将 Hibernate Session 保留为 Controller 的“实例变量” - 或者作为某个地方的静态变量。永远不应该这样做。

由于 Web 请求可能是并发的,因此控制器不应该将请求处理状态(例如 Hibernate Sessions 或可变变量)共享为实例变量。这将导致单独的请求和线程之间发生不必要的交互。

于 2013-07-24T01:53:09.793 回答
1

对不起,我不能用行空格写,所以我写一个新的答案。

问题可能是我之前在您的答案评论中输入的文字?我这样声明类控制器。

@Controller
public class HelloController {

    @RequestMapping(value="/hello.htm")
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

我多次创建的对象是 HttpServletRequest 和 Response?或者是另一个?

我不知道我在哪里创建 SessionFactory。

另一个可能的地方,可能是在 Dao 中,我在所有 Dao 中声明一个这样的实体管理器。

@Repository(value = "contratoDao")
public class JPAContratoDao implements ContratoDao {

    private EntityManager em = null;

    /*
     * Sets the entity manager.
     */
    @PersistenceContext
    public void setEntityManager(EntityManager em) {
        this.em = em;
    }

其中一些可能是问题所在?

再次感谢!

于 2013-07-24T19:29:22.377 回答
1

好的。谢谢。

我应该如何声明EntityManager?

我正在阅读 Springsource 中 Hibernate 的链接,但在我的代码中看不到任何多余的东西。我不知道我该怎么办...

我的 applicationContext.xml 是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">


    <!-- holding properties for database connectivity /-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- enabling annotation driven configuration /-->
    <context:annotation-config/>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="${jdbc.driverClassName}"/>
      <property name="url" value="${jdbc.url}"/>
      <property name="username"  value="${jdbc.username}"/>
      <property name="password" value="${jdbc.password}"/>
    </bean>

    <bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
            p:dataSource-ref="dataSource"
            p:jpaVendorAdapter-ref="jpaAdapter">
            <property name="loadTimeWeaver">
              <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
            </property>                             
            <property name="persistenceUnitName" value="springappPU"></property>
    </bean>

    <bean id="jpaAdapter"
            class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
            p:database="${jpa.database}"
            p:showSql="${jpa.showSql}"/>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
            p:entityManagerFactory-ref="entityManagerFactory"/>

    <tx:annotation-driven transaction-manager="transactionManager"/>


    <!-- Scans the classpath of this application for @Components to deploy as beans -->
    <context:component-scan base-package="com.companyname.springapp.repository" />
    <context:component-scan base-package="com.companyname.springapp.service" />

</beans>

我必须如何制作 applicationContext.xml?以及我应该如何在类中声明 EntityManager?

还是您认为我应该使用 SessionFactory?

带来不便敬请谅解。

于 2013-07-25T20:18:25.983 回答