gpt4 book ai didi

java - session 和事务的线程使用导致内存泄漏?

转载 作者:行者123 更新时间:2023-11-28 22:57:44 24 4
gpt4 key购买 nike

我正在寻找 JSF 应用程序中的内存泄漏。我读过各种文章,讨论在事务和 session 中使用线程时潜在的内存泄漏。以下代码看起来是否会产生泄漏?此代码被调用数千次(用于页面请求)。

public class HibernateHelper 
{
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTransaction = new ThreadLocal();

public static Session startSessionWithDBName(SessionFactorySingleton.DBname dbname)
{
Session s = getSessionWithDBName(dbname);
beginTransaction(dbname);
return s;
}

@SuppressWarnings("unchecked")
private static Session getSessionWithDBName(SessionFactorySingleton.DBname dbname)
{
Session s = (Session) threadSession.get();
if (s == null)
{
s = SessionFactorySingleton.getSessionFactory(dbname).openSession();
threadSession.set(s);
}
else
{
String sf = ((SessionFactoryImpl)s.getSessionFactory()).getProperties().getProperty("hibernate.session_factory_name");
if((dbname !=null && sf !=null) && !sf.equals(dbname.toString()))
{
closeSessionBySessionFactoryName(sf);
s = SessionFactorySingleton.getSessionFactory(dbname).openSession();
threadSession.set(s);
}
}
return s;
}

@SuppressWarnings("unchecked")
public static boolean isSessionOpen()
{
Session s = (Session) threadSession.get();
if (s != null)
return s.isOpen();
return false;
}

public static boolean wasTransactionCommited()
{
Transaction t = (Transaction) threadTransaction.get();
if (t != null)
return t.wasCommitted();
return false;
}

@SuppressWarnings("unchecked")
public static void closeSessionBySessionFactoryName(String sessionfactoryname) {
Session s = (Session) threadSession.get();
if (s != null && s.isOpen())
{
String sfname = ((SessionFactoryImpl)s.getSessionFactory()).getProperties().getProperty("hibernate.session_factory_name");
if(sfname.equals(sessionfactoryname))
{
try
{
commitTransaction(sfname);
} catch (Exception e) {
e.printStackTrace();
}
s.close();
threadSession.set(null);
}
}
}

/**
* Start a new database transaction.
*/
private static void beginTransaction(SessionFactorySingleton.DBname dbname) {
Session s = (Session) threadSession.get();
if(s!=null)
{
log.info("Starting new transaction for this thread.");
Transaction tx = s.beginTransaction();
threadTransaction.set(tx);
}
}

/**
* Commit the database transaction.
*/
public static void commitTransaction(String sessionfactoryname) throws Exception {
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
tx.commit();
log.info("Committed transaction for thread "+ Thread.currentThread().getName());
}
threadTransaction.set(null);
} catch (Exception e)
{
log.error("Exception when committing transaction: ", e);
rollbackTransactionKeepingSessionOpen();
throw e;
}
}

/**
* Rollback the database transaction.
*/
public static void rollbackTransactionKeepingSessionOpen() {
Transaction tx = (Transaction) threadTransaction.get();
threadTransaction.set(null);
if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
tx.rollback();
}
}

}

最佳答案

是的。
每个 threadLocal 实例都绑定(bind)到使用它的线程的生命周期。
Tomcat的线程池可以轻松拥有上百个线程;每个线程都被重用且永不销毁。
其中一些会卡在 I/O 操作、查询 DB 或诸如此类的东西,同时持有对打开的 Hibernate session 的引用(这反过来可能包含许多附加实体)。
所以在某些时期,应用程序可能有许多无法被GC回收的大对象图。
我认为您应该以不同的方式管理 Hibernate session 和事务。

关于java - session 和事务的线程使用导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23902621/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com