-
为什么我用hibernate创建的对象不被垃圾回收(即使会话过期也不消失)40
为什么Hibernate创建的对象不被销毁呢?
如图(1)先用hibernate查询,创建了36(TMain.java)个对象
然后再用jdbc查询如图(2)创建了37(TMain2.java)个对象
系统设置会话过期时间为2分钟
会话过期后如图(3)jdbc创建的对象消失了36个,而hibrenate创建的对象一个也没有消失,并且可以看到CGLIB代理对象也没有消失
这是为什么?小弟不才,没有仔细读过hibernate源代码,对其中原因不明。希望各位帮助解惑,版主请别删贴。
图(1)
图(2)
图(3)
WEB.xml<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>service</servlet-name> <servlet-class>org.test.Service</servlet-class> </servlet> <servlet-mapping> <servlet-name>service</servlet-name> <url-pattern>/servlet/service</url-pattern> </servlet-mapping> <session-config> <!-- 这里为了测试,设置session国企时间为2分钟 --> <session-timeout>2</session-timeout> </session-config> </web-app>
Hibernate.cfg.xml (hibernate 配置文件)<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.username">sa</property> <property name="connection.url">jdbc:jtds:sqlserver://127.0.0.1:1433/fast</property> <property name="dialect">org.hibernate.dialect.SQLServerDialect</property> <property name="myeclipse.connection.profile">jtds</property> <property name="connection.password">yourgame</property> <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property> <property name="show_sql">true</property> <mapping resource="org/test/TMain.hbm.xml" /> </session-factory> </hibernate-configuration>
Service.javapackage org.test; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.hibernate.Session; @SuppressWarnings("serial") public class Service extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method = request.getParameter("method"); List list = null; if (method.equals("hibernate")) { // 判断查询的方式 list = this.hibernate(request, response); } if (method.equals("jdbc")) { list = this.jdbc(request, response); } request.setAttribute("list", list); //将查询的结果集放入request中 request.getRequestDispatcher("/index.jsp").forward(request, response); } /** * 2008-7-1-上午11:05:41 * * 功能:通过Hibernate来查询对象返回集合 * */ private List hibernate(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Session session = HibernateUtils.getSession(); session.beginTransaction(); List list = session.createQuery("from TMain").list(); session.getTransaction().commit(); HibernateUtils.closeSession(session); return list; } /** * 2008-7-1-上午11:06:20 * * 功能:通过jdbc查询对象返回集合,Utils.list()方法将结果集封装成javabean * */ private List jdbc(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { return Utils.list(new TMain2(), "t_main", null, new Conn()); } }
TMain.java (这个javabean用户Hibernate映射)package org.test; public class TMain implements java.io.Serializable { private Integer id; private String uuid; 其他字段和setter,getter() 略……… TMain2.java(和TMain.java 一样,这个javabean用于jdbc结果集封装)
问题补充:
package com.bjsxt.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static SessionFactory factory;
private HibernateUtils() {
}
static {
Configuration cfg = new Configuration().configure();
factory = cfg.buildSessionFactory();
}
public static SessionFactory getSessionFactory() {
return factory;
}
public static Session getSession() {
return factory.openSession();
}
public static void closeSession(Session session) {
if (session != null) {
if (session.isOpen()) {
session.close();
}
}
}
}
问题补充:
请问wangxin0072000
您指的是不是spring的OpenSessionInView ???
问题补充:
请问wangxin0072000:
OpenSessionInView 的作用就是把hiernate的Session保持到页面或者说保持到请求完成后再关闭吗?
问题补充:
请问请问wangxin0072000:
我按照您说的调用System.gc();
效果可以,但是还有一些对象没有消失,org.test.TMain$$BulkBeanByCGLIB$$6d008257
org.test.TMain$$FastClassByCGLIB$$2519251b
org.test.Service
org.test.TMain
以上类的实例都还存在一个实例不被回收,请问这是什么原因呢?
问题补充:
请问wangxin0072000
按照您说的调用System.gc()方法很凑效,对象大部分都消失了
但是还有四个实例不被回收
分别是
org.test.TMain (1个)
org.test.Service (1个)
org.test.TMain$$FastClassByCGLIB$$2519251b (1个)
org.test.TMain$$BulkBeanByCGLIB$$6d008257 (1个)
无论我调用多少次System.gc() 这些对象也不会被回收
请您帮助2008年7月02日 16:39
6个答案 按时间排序 按投票排序
-
采纳的答案
那么有可能是垃圾回收器一直没有回收。你试试手动回收一下。
见:public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method = request.getParameter("method"); List list = null; if (method.equals("hibernate")) { // 判断查询的方式 list = this.hibernate(request, response); } if (method.equals("jdbc")) { list = this.jdbc(request, response); } if (method.equals("gc")) { System.gc( ); list=new ArrayList(); } request.setAttribute("list", list); //将查询的结果集放入request中 request.getRequestDispatcher("/index.jsp").forward(request, response); }
之后等用hibernate测完之后,用method=gc为参数再来一次。之后再看看。2008年7月02日 21:16
-
org.test.TMain$$FastClassByCGLIB$$2519251b (1个) 不应该被回收,这个是是org.test.TMain的代理类。Hibernate就是使用cglib来增强普通java对象的。对于代理类保留一个Class对象,那下次你load TMain就不会再创建了。
org.test.TMain$$BulkBeanByCGLIB$$6d008257 (1个) 具体是什么作用则需要研究cglib的类库了。估计是对对象的setter和getter进行快速操作的类。
org.test.TMain (1个) 估计是被org.test.TMain$$BulkBeanByCGLIB$$6d008257引用的一个副本。
org.test.Service (1个) 这个就没有看到代码,不好猜测。
2008年7月03日 12:09
-
OpenSessionInView是保证每个访问servlet用户的线程都能从spring的配置文件中得到hibernate的session。我说的那个过滤器具体是什么我也忘了,我明天去看看,好想与你写的HibernateUtils中的closeSession类似。我始终认为是垃圾回收器一直没有回收。看hibernate的源码:
public Connection close() throws HibernateException { log.trace( "closing session" ); if ( isClosed() ) { throw new SessionException( "Session was already closed" ); } if ( factory.getStatistics().isStatisticsEnabled() ) { factory.getStatisticsImplementor().closeSession(); } try { try { if ( childSessionsByEntityMode != null ) { Iterator childSessions = childSessionsByEntityMode.values().iterator(); while ( childSessions.hasNext() ) { final SessionImpl child = ( SessionImpl ) childSessions.next(); child.close(); } } } catch( Throwable t ) { // just ignore } if ( rootSession == null ) { return jdbcContext.getConnectionManager().close(); } else { return null; } } finally { setClosed(); cleanup(); } }
最后有个cleanup();
再看这个方法的注释:/** * clear all the internal collections, just * to help the garbage collector, does not * clear anything that is needed during the * afterTransactionCompletion() phase */ private void cleanup() { persistenceContext.clear(); }
可见在close的同时已经清除了所有持久化对象与Session的关联了。所以这些对象肯定是游离状态。2008年7月02日 23:58
-
楼主的代码有一些问题:
1、hibernate的session建立了一级缓存,对于session的获取以基于线程局部变量(ThreadLocal)方式存取比较合理。
2、对于关闭后,如2楼楼主所言,查出来的对象变成游离状态,但是否被垃圾回收,而与HttpServlet的会话时间长短无关。
3、对于查询,不需要事务,不需要获得表的独占或共享级别锁。
4、在Servlet中直接进行数据库操作的方式比较地不好。2008年7月02日 21:19
-
1 会话销毁,是指在servlet容器中存放的session信息销毁。与hibernate无关。
2 而hibernate创建的对象与hibernate的session相关。如果你关闭了session后,这些创建的对象就会成为游离状态,当内存不足的时候,JAVA的垃圾回收机制就会回收游离状态的对象。
3 仔细看看你的代码,你没有关闭session所以自然不会回收,这也就是hibernate造成的内存泄漏问题,这也就是为什么spring中会用一个过滤器关闭与这条线程相关的hibernate.session了。2008年7月02日 20:51
相关推荐
Hibernate 工作原理及为什么要用 Hibernate 作为一个开放源代码的对象关系映射框架,对 JDBC 进行了轻量级的对象封装,使 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。下面将详细介绍 Hibernate 的...
- **merge()**: 将脱管对象的状态合并到当前的持久化上下文中,即使对象的属性没有变化,也会更新数据库记录。通常用于确保对象的最新状态被保存。 理解 Hibernate 对象状态及其转换对于有效管理和优化数据库操作至...
Hibernate的核心在于提供对象-关系映射(ORM)服务,使得开发者能够以面向对象的方式来管理和操作数据库中的数据,从而减少了直接使用JDBC进行数据操作时的复杂性和错误。 为什么需要Hibernate? 在传统的JDBC编程中...
一旦一个对象被持久化,它就处于Hibernate的管理之下,其生命周期将与数据库记录绑定。Hibernate提供了四种对象状态:瞬时态、持久态、脱管态和临时态,理解这些状态对于有效操纵持久化对象至关重要。 **三、配置...
如果对象不再被引用,它们会被垃圾回收器回收。瞬时对象不处于任何Session的缓存中,数据库中也没有对应的记录。Hibernate的`delete()`方法可以使持久化对象或游离对象变为瞬时对象。 2. **持久化对象(Persist ...
在Java世界里,Hibernate是一个非常流行的ORM(对象关系映射)框架,它允许开发者使用面向对象的方式来操作数据库,而无需直接编写SQL语句。本文将深入探讨如何在Hibernate中创建数据库表,以此来构建实际的应用。 ...
如果对象在临时状态下被垃圾收集器清理,那么这个对象在数据库中的记录并不会受到影响,因为它们之间没有绑定关系。如果想要使对象进入持久状态,需要通过Session的`save()`、`saveOrUpdate()`或`persist()`方法。 ...
添加Hibernate特性:由于Hibernate反向工程功能要求项目支持Hibernate,所以在进行实体对象生成之前,需要为项目添加Hibernate特性。这包括选择Hibernate版本、设置JAR库安装位置、配置数据库驱动等。 e. 生成...
它们没有持久化标识(ID),在Hibernate的眼里,这些对象就像普通的Java对象,如果程序结束或者对象引用丢失,这些对象就会被垃圾回收器清除,数据不会保存到数据库中。在Hibernate中,通过`new`关键字创建的对象...
【使用Hibernate完成对象持久化】 在Java开发中,对象持久化是将应用程序中的对象与数据库中的数据进行绑定,使得对象的状态能够在系统重启后仍然保持。Hibernate是一个强大的对象关系映射(ORM)框架,它简化了...
《精通Hibernate:Java对象持久化技术详解》这本书深入剖析了Hibernate这一流行的Java对象关系映射(ORM)框架,旨在帮助开发者全面理解并熟练掌握Hibernate的使用。Hibernate是Java开发中的重要工具,它简化了...
本文主要探讨的是在使用Hibernate框架时遇到的“Hibernate3.4 不自动创建索引的问题”。Hibernate是一个优秀的对象关系映射(ORM)框架,它允许开发者用Java对象的方式来操作数据库,而无需过多关注SQL的细节。然而...
在这个主题“hibernate操纵实体对象”中,我们将探讨如何使用Hibernate来创建、更新、删除和查询数据库中的实体对象。 首先,`HibernateSessionFactory`是Hibernate的核心组件之一,它负责创建`Session`对象。`...
这三种状态分别对应了对象与数据库的关联程度,理解它们对于高效地使用Hibernate进行数据操作至关重要。 ### 1. 持久态(Persistent) **持久态**是指对象已经被Hibernate管理,并且其状态与数据库中的记录同步。...
在Java开发中,Hibernate是一个非常重要的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用面向对象的方式来处理数据。然而,随着Java JDK版本的不断更新,有时会出现新版本JDK与旧版Hibernate库...
如果没有任何引用指向这个对象,JVM的垃圾回收机制将会回收它。 - 临时对象与数据库没有任何联系。要使这个对象与数据库关联并将其数据保存或更新到数据库,需要调用`Session`的`save`或`saveOrUpdate`方法,这样...
一旦应用程序不再引用这些对象,它们就会被垃圾回收机制清除。瞬时对象的特征如下: - 不在Session的缓存中。 - 数据库中没有对应的记录。 - 可以通过Session的`delete()`方法将持久化对象或游离对象转化为瞬时...
在Java开发中,Hibernate是一款非常重要的对象关系映射(ORM)框架,它极大地简化了数据库操作,使得开发者可以使用面向对象的方式来处理数据库数据。本篇文章将深入探讨Hibernate中的实体对象操纵,包括实体的概念...
- **解释**:使用 `Configuration` 对象创建 `SessionFactory`,`SessionFactory` 是线程安全的,可以被多个线程共享使用。 **3. 创建 Session 会话对象** ```java Session session = sessionFactory.openSession...