【发布时间】:2014-07-17 03:29:35
【问题描述】:
我正在寻找 JSF 应用程序中的内存泄漏。我已经阅读了各种文章,讨论了在将线程与事务和会话一起使用时潜在的内存泄漏。下面的代码似乎会产生泄漏吗?这段代码被调用了数千次(用于页面请求)。
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();
}
}
}
【问题讨论】:
-
使用分析器并找到产生内存泄漏的堆栈位置。
标签: java multithreading jsf tomcat memory-leaks