`
yaojialing
  • 浏览: 255456 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Hibernate3.1.X 多线程下BUG

    博客分类:
  • JAVA
阅读更多

刚写过一篇Java笔记-使用JConsole进行JVM性能监测,今天就又遇上99%,乐不开支拍拍手打开JConsole就要收拾它。

 

在Thread选项卡中看到许多HTTP的请求线程都阻塞在org.hibernate.util.SoftLimitMRUCache.get(SoftLimitMRUCache.java:51)   很快就发现下面这个Thread

 

Name: TP-Processor24
State: RUNNABLE
Total blocked: 87  Total waited: 21

 

Stack trace:
org.apache.commons.collections.ReferenceMap.getEntry(Unknown Source)
org.apache.commons.collections.ReferenceMap.get(Unknown Source)
org.hibernate.util.SoftLimitMRUCache.get(SoftLimitMRUCache.java:51)
org.hibernate.engine.query.QueryPlanCache.getNativeSQLQueryPlan(QueryPlanCache.java:107)
org.hibernate.impl.AbstractSessionImpl.getNativeSQLQueryPlan(AbstractSessionImpl.java:140)
org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:147)
org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:164)
com.mogoko.struts.logic.user.LeaveMesManager.getCommentByShopId(LeaveMesManager.java:302)
com.mogoko.struts.action.shop.ShopIndexBaseInfoAction.execute(ShopIndexBaseInfoAction.java:175)

 

 

 

LeaveMesManager.java:302是下面

 

list = (ArrayList) session.createSQLQuery(queryString).addEntity(“”,Leavemes.class).list();

 

 

 

显然是TP-Processor24进入SoftLimitMRUCache.get—>ReferenceMap.get–>ReferenceMap.getEntry没有返回,一共87个Thread被阻塞(21代表什么呢?)。

 

我们的环境如下:

 

Hibernate 3.1.2

 

Collections:2.1.1

 

分别打开了SoftLimitMRUCache.java和ReferenceMap.java。后者extends自AbstractMap,本身不提供线程安全保证,那就是SoftLimitMRUCache的问题了。看下面它的代码

 

 

 

 

 


public synchronized Object get(Object key) {
  Object result = softReferenceCache.get( key );//   第51行
  if ( result != null ) {
   strongReferenceCache.put( key, result );
  }
  return result;
 }

 

 public Object put(Object key, Object value) {
  softReferenceCache.put( key, value );
  return strongReferenceCache.put( key, value );
 }

 

 public int size() {
  return strongReferenceCache.size();
 }

 

 public int softSize() {
  return softReferenceCache.size();
 }

 

 public Iterator entries() {
  return strongReferenceCache.entrySet().iterator();
 }

 

 public Iterator softEntries() {
  return softReferenceCache.entrySet().iterator();
 }

 

 

 

get函数外都没有synchronized,顶你的肺      看样子是每一次Hibernate’s Query在调用JDBC查询前都会去这个SoftLimitMRUCache先尝试从内存中查,从而减少数据库负载,之所以1次/周,是源于访问量不大,没有做好压力测试啊  

 

再看看ReferenceMap.java

 


    public Object get(Object key) {
        purge();
       
Entry entry = getEntry(key);       //   调用getEntry
        if (entry == null) return null;
        return entry.getValue();
    }


    private Entry getEntry(Object key) {
        if (key == null) return null;
        int hash = key.hashCode();
        int index = indexFor(hash);
       
for (Entry entry = table[index]; entry != null; entry = entry.next) {
            if ((entry.hash == hash) && key.equals(entry.getKey())) {
                return entry;
            }
        }
        return null;
    }


    public Object put(Object key, Object value) {
        if (key == null) throw new NullPointerException(“null keys not allowed”);
        if (value == null) throw new NullPointerException(“null values not allowed”);


        purge();
        if (size + 1 > threshold) resize();


        int hash = key.hashCode();
        int index = indexFor(hash);
        Entry entry = table[index];
       
while (entry != null) {
            if ((hash == entry.hash) && key.equals(entry.getKey())) {
                Object result = entry.getValue();
                entry.setValue(value);
                return result;
            }
            entry = entry.next;
        }
        this.size++;
        modCount++;
        key = toReference(keyType, key, hash);
        value = toReference(valueType, value, hash);
        table[index] = new Entry(key, hash, value, table[index]);
        return null;
    }


    private void resize() {
        Entry[] old = table;
        table = new Entry[old.length * 2];


        for (int i = 0; i < old.length; i++) {
            Entry next = old[i];
            while (next != null) {
                Entry entry = next;
                next = next.next;
                int index = indexFor(entry.hash);
                entry.next = table[index];
                table[index] = entry;
            }
            old[i] = null;
        }
        threshold = (int)(table.length * loadFactor);
    }


注意上面的四行粗蓝色代码,最多有三处会循环遍历/修改链表,多Thread环境下导致链表出现环路,结果infinite loop!


在Hibernate官网找到SoftLimitMRUCache的bug,有两条


1    Concurrent access issues with both SoftLimitMRUCache and SimpleMRUCache


影响版本3.2.0.alpha1, 3.1.3 


再看看这个Infinite Loop Possible Through Non-synchronisd use LRUMap


讲的虽然是LRUMap,但根本原因仍在于SoftLimitMRUCache除get函数外没有同步导致。


对非同步的map多线程下带来的问题感兴趣可以看这里


HashMap.get() can cause an infinite loop!


2    Use of session.createSQLQuery causes memory leak


 内存泄漏同样由于线程非安全导致。


 


下载Hibernate3.2.1的源码如下


 


public synchronized Object put(Object key, Object value) {
  softReferenceCache.put( key, value );
  return strongReferenceCache.put( key, value );
 }


 public synchronized int size() {
  return strongReferenceCache.size();
 }


 public synchronized int softSize() {
  return softReferenceCache.size();
 }


 public synchronized void clear() {
  strongReferenceCache.clear();
  softReferenceCache.clear();
 }


 


新版本中get/put/size/softSize函数和新增的clear函数都加上了synchronized同步。


 


 


Hibernate的bug查询地址是http://opensource.atlassian.com/projects/hibernate/secure/IssueNavigator.jspa


 


 


赶紧扔掉你的Hibernate3.1.X,换到Hibernate3.2.1以上吧,如果还有死循环问题我会。。

源自:http://www.mogoko.com/p/article/2385

分享到:
评论

相关推荐

    Spring 3.1.x + Hibernate 4.2.x+JBPM 5.2 + Ecache例子源码

    标题中的"Spring 3.1.x + Hibernate 4.2.x + JBPM 5.2 + Ecache例子源码"代表了一个集成开发环境,其中包含了四个关键的技术组件: 1. **Spring 3.1.x**:这是一个开源的应用框架,主要用于简化Java企业级应用的...

    hibernate3.1. jar

    标题提到的 "hibernate3.1. jar" 是 Hibernate 3.1 版本的库文件,这是该框架的一个较旧版本。这个版本在当时引入了许多增强功能和改进,包括性能优化、对JPA(Java Persistence API)的支持以及更好的错误处理机制...

    Hibernate 3.1.pdf

    2. **配置文件**:Hibernate的配置文件(hibernate.cfg.xml)是系统启动时必需的,它包含了数据库连接信息、缓存配置、方言设置等关键参数。 3. **SessionFactory和Session**:SessionFactory是Hibernate的单例对象...

    Spring 3.1.x + Hibernate 4.2.x+JBPM 5.2 + Ecache例子

    标题 "Spring 3.1.x + Hibernate 4.2.x + JBPM 5.2 + Ecache 例子" 涉及的是一个集成多种技术的Java应用开发示例。这个项目可能是一个完整的业务流程管理系统,它整合了Spring、Hibernate、JBPM和Ecache等关键组件。...

    Struts2.X+Hibernate3.X+Spring2.5 整合

    Hibernate的配置文件(hibernate.cfg.xml)用于设置数据库连接参数,实体类需要通过注解或XML映射文件与数据库表进行关联。Spring的配置文件(applicationContext.xml)则用于声明bean并管理它们的生命周期和依赖...

    Hibernate3.1的jar包

    Hibernate3.1的jar包 Hibernate3.1的jar包 Hibernate3.1的jar包 Hibernate3.1的jar包 Hibernate3.1的jar包 Hibernate3.1的jar包 Hibernate3.1的jar包

    struts1.2+spring2.0+hibernate3.1jar包

    在集成这三个框架时,开发者需要配置多个XML文件,如struts-config.xml、spring-servlet.xml和hibernate.cfg.xml,定义组件间的依赖关系和数据库连接信息。这种组合在当时的Java Web开发中非常流行,但由于技术的...

    struts2.3.x+spring3.1.x+hibernate4.1整合工程(好用)

    这里我们详细探讨一下"Struts2.3.x+Spring3.1.x+Hibernate4.1整合工程"的相关知识点。 **Struts2** 是一个基于MVC设计模式的Java Web框架,它主要用于处理HTTP请求和响应,提供了强大的表单验证、国际化支持以及...

    Struts 2.1 + Spring 2.0.8 + Hibernate 3.1.rar

    此版本还包括了对CGLIB和Javassist动态代理库的支持,以及对多线程和并发的优化。通过Hibernate,开发者可以避免编写大量的SQL代码,提高开发效率并降低维护成本。 将这三个框架整合在一起,可以构建出一个强大的...

    hibernate3.1.CHM

    hibernate3 API CHM 版本

    hibernate-3.1.zip

    2. **配置文件**:在压缩包中可能包含`hibernate.cfg.xml`,这是Hibernate的配置文件,用于设置数据源、JDBC连接参数、方言、缓存策略等。理解如何配置这些参数对于正确使用Hibernate至关重要。 3. **实体类...

    struts1.2+spring2.0+hibernate3.1框架所需jar包

    在这个“struts1.2+spring2.0+hibernate3.1框架所需jar包”压缩包中,包含了这三个框架的核心库和其他必要的依赖,以便于开发者在项目中集成和使用。 **Struts 1.2** 是一个基于MVC设计模式的Java Web框架,它使得...

    hibernate3.1的jar 很全

    以下JAR包: antlr-2.7.5H3.jar asm.jar cglib-2.1.2.jar commons-collections-2.1.1.jar commons-pool.jar dom4j-1.6.1.jar ehcache-1.1.jar hibernate3.jar jta.jar log4j-1.2.11.jar Standard.jar

    hibernate3.1 jar包

    ehcache-1.1.jar (1.1) - EHCache cache - runtime, optional (required if no other cache provider is set) versioncheck.jar (1.0) - version checker - buildtime swarmcache-1.0rc2.jar (1.0rc2) ...

    hibernate4.x jar

    Hibernate 4.x 是一个流行的Java持久化框架,用于简化数据库操作和对象关系映射(ORM)。这个"hibernate4.x jar"包包含了 Hibernate 框架的核心组件和其他相关库,便于开发者在自己的项目中使用。它使得开发人员能够...

    hibernate3.1

    《深入理解Hibernate 3.1:核心库与实践探索》 Hibernate 3.1是一款流行的开源对象关系映射(ORM)框架,它极大地简化了Java应用程序对数据库的操作。本篇文章将详细探讨该版本中的核心库内容及其实用特性,帮助...

    struts2.3.x+spring3.1.x+hibernate3.6 demo

    关键问题有几个,第一个HibernateDaoSupport这个没有了,在使用hibernateTemplate的时候,报错误:java.lang.NoSuchMethodError: org.hibernate.SessionFactory.openSession()Lorg/hibernate/classic/Session 很是悲...

    妙解Hibernate 3.x:叩响面向对象思想之门 PDF

    《妙解Hibernate 3.x:叩响面向对象思想之门》是一本深入解析Hibernate框架的专著,旨在帮助读者理解并掌握面向对象编程思想在实际开发中的应用,尤其是在使用Hibernate时如何有效地进行数据持久化。这本书是面向...

    springmvc, spring5.x , hibernate5.x 整合

    整合Spring MVC、Spring 5.x和Hibernate 5.x,我们可以构建一个强大的后端系统。首先,我们需要在Spring配置中声明Hibernate的DataSource和SessionFactory,然后通过Spring的JdbcTemplate或Hibernate的Session接口...

Global site tag (gtag.js) - Google Analytics