Java org.hibernate.internal.SessionFactoryImpl可能导致内存泄漏

Java org.hibernate.internal.SessionFactoryImpl可能导致内存泄漏,java,hibernate,memory-leaks,out-of-memory,Java,Hibernate,Memory Leaks,Out Of Memory,我已经用Java制作了和MVC webapp,但当我每天运行一次时,由于内存错误,它再次关闭 此错误如下所示: 线程“http-apr-12136-exec-42”java.lang.OutOfMemoryError中出现异常:java堆空间 java.sql.SQLException:java.lang.OutOfMemoryError:java堆空间 我有hprof和崩溃的统计数据,其中具体如何使用内存。如果使用Eclipse内存分析器打开hprof,则会得到以下结果: 在rar中: 或在文

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

此错误如下所示: 线程“http-apr-12136-exec-42”java.lang.OutOfMemoryError中出现异常:java堆空间

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

我有hprof和崩溃的统计数据,其中具体如何使用内存。如果使用Eclipse内存分析器打开hprof,则会得到以下结果:

在rar中:

或在文件夹中:

在概览报告中,我有以下图形(overviewma.JPG): 我不知道这张图怎么说。。。我不明白

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

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

如果我展开第一个类(给出问题的类),我会看到这个图形(dominatortreexpanded_EMA.JPG):

在下一个选项卡的直方图中,图形如下(histogram_EMA.JPG):

在不可访问对象中,结果如下(UnreachableObjects_EMA.JPG):

我不太明白最后两幅图

最后,我还有Java VisualVM的报告,其中有以下结果(Heapdump_JVM.JPG):

根据此图,除了整数和字符串对象之外,HashMap对象也是问题所在。我认为Hashmap对象是类发送到jsp文件的模型对象,它来自JPA对象(Hibernate的对象),所以问题可能是这个,但我不知道如何解决它

有人能帮我吗?有人知道我该怎么修吗?你需要更多的信息吗


谢谢

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

另请参阅下面我关于正确使用Hibernate会话的评论


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

我怀疑,因为您要退出内存,所以您正在将Hibernate会话保持为控制器的“实例变量”——或者作为某个地方的静态会话。这是绝对不应该做的


由于web请求可能是并发的,控制器不应将请求处理状态(如Hibernate会话或可变变量)作为实例变量共享。这将在单独的请求和线程之间造成不必要的交互。

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

问题可能是我之前在你回答的评论中提到的文本?我像这样声明类控制器

@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;
    }
其中一些可能是问题所在

再次感谢

好的。谢谢

我应该如何声明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


很抱歉给您带来不便。

谢谢。我正在尝试这样做,但我不知道如何使用OpenSessionInView。你认为控制器有问题吗?也许是这个@控制器公共类HelloController{@RequestMapping(value=“/hello.htm”)公共模型和视图HandlerRequest(HttpServletRequest,HttpServletResponse)抛出ServletException,IOException{Controller很好,您在设置SessionFactory或ApplicationContext时可能会遇到一些奇怪的情况。无论您在做什么,您都会在应该做一次的时候做很多次。请参阅:我不喜欢EntityManager被声明为DAO中的实例变量。如果这是DAO服务/Facade/Manager,而不是数据实体,这是错误的。EntityManager(hibernate会话)是针对每个web请求的,对于不同的线程是不同的,而不是在应用程序的生命周期中保持和增长/积累数据。共享HB会话(JPA EntityManager)对于多用户/并发使用也是完全不正确的。好吧。我又仔细阅读了Spring教程。你说我不应该共享HB会话。这是事实吗?如果你这么说,我该怎么办?我必须使用SessionFactory而不是EntityManager吗?或者我应该更改我的applicationContext或我的JPADao声明吗?使用SessionFactoryUti吗ls.getSession()获取当前会话,OpenSessionInView筛选器在请求处理和查看(JSP)期间将Hibernate会话绑定到当前线程呈现。Hibernate会话应该是每个请求的,而不是长期的和全局共享的,因为这是导致永久增长和OOM问题的原因,而且从线程和多用户的角度来看是完全不正确的。您也可以使用SessionFactory或EntityManagerFactory(JPA等效),并为每个方法调用创建一个会话/EntityManager