循环打印java.util.ConcurrentModificationException

 java.util.ConcurrentModificationException

的原因:

 

的原因:

 

 

报错位置是

         at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)

         at java.util.HashMap$KeyIterator.next(HashMap.java:828)

         at org.hibernate.jdbc.AbstractBatcher.closeStatements(AbstractBatcher.java:314)

         at org.hibernate.jdbc.ConnectionManager.cleanup(ConnectionManager.java:382)

         at org.hibernate.jdbc.ConnectionManager.close(ConnectionManager.java:324)

         at org.hibernate.impl.SessionImpl.close(SessionImpl.java:298)

         at org.hibernate.ejb.EntityManagerImpl.close(EntityManagerImpl.java:86)

 

 

查回源码(hibernate3.2.4 sp1

 

        

 

	/**
	 * Actually releases the batcher, allowing it to cleanup internally held
	 * resources.
	 */
	public void closeStatements() {
		try {
			releasing = true;

			try {
				if (batchUpdate!=null) batchUpdate.close();
			}
			catch (SQLException sqle) {
				//no big deal
				log.warn("Could not close a JDBC prepared statement", sqle);
			}
			batchUpdate=null;
			batchUpdateSQL=null;

			Iterator iter = resultSetsToClose.iterator();
			while ( iter.hasNext() ) {
				try {
					logCloseResults();
					( (ResultSet) iter.next() ).close();
				}
				catch (SQLException e) {
					// no big deal
					log.warn("Could not close a JDBC result set", e);
				}
				catch (Throwable e) {
					// sybase driver (jConnect) throwing NPE here in certain cases
					log.warn("Could not close a JDBC result set", e);
				}
			}
			resultSetsToClose.clear();

			iter = statementsToClose.iterator();
			while ( iter.hasNext() ) {
				try {
					closeQueryStatement( (PreparedStatement) iter.next() );
				}
				catch (SQLException e) {
					// no big deal
					log.warn("Could not close a JDBC statement", e);
				}
			}
			statementsToClose.clear();
		}
		finally {
			releasing = false;
		}
	}

 

 

 

 

 

 

 

 

查回源码(hibernate3.2.7 ga

 

 

	/**
	 * Actually releases the batcher, allowing it to cleanup internally held
	 * resources.
	 */
	public void closeStatements() {
		try {
			releasing = true;

			try {
				if ( batchUpdate != null ) {
					batchUpdate.close();
				}
			}
			catch ( SQLException sqle ) {
				//no big deal
				log.warn( "Could not close a JDBC prepared statement", sqle );
			}
			batchUpdate = null;
			batchUpdateSQL = null;

			Iterator iter = resultSetsToClose.iterator();
			while ( iter.hasNext() ) {
				try {
					logCloseResults();
					( ( ResultSet ) iter.next() ).close();
				}
				catch ( SQLException e ) {
					// no big deal
					log.warn( "Could not close a JDBC result set", e );
				}
				catch ( ConcurrentModificationException e ) {
					// this has been shown to happen occasionally in rare cases
					// when using a transaction manager + transaction-timeout
					// where the timeout calls back through Hibernate's
					// registered transaction synchronization on a separate
					// "reaping" thread.  In cases where that reaping thread
					// executes through this block at the same time the main
					// application thread does we can get into situations where
					// these CMEs occur.  And though it is not "allowed" per-se,
					// the end result without handling it specifically is infinite
					// looping.  So here, we simply break the loop
					log.info( "encountered CME attempting to release batcher; assuming cause is tx-timeout scenario and ignoring" );
					break;
				}
				catch ( Throwable e ) {
					// sybase driver (jConnect) throwing NPE here in certain
					// cases, but we'll just handle the general "unexpected" case
					log.warn( "Could not close a JDBC result set", e );
				}
			}
			resultSetsToClose.clear();

			iter = statementsToClose.iterator();
			while ( iter.hasNext() ) {
				try {
					closeQueryStatement( ( PreparedStatement ) iter.next() );
				}
				catch ( ConcurrentModificationException e ) {
					// see explanation above...
					log.info( "encountered CME attempting to release batcher; assuming cause is tx-timeout scenario and ignoring" );
					break;
				}
				catch ( SQLException e ) {
					// no big deal
					log.warn( "Could not close a JDBC statement", e );
				}
			}
			statementsToClose.clear();
		}
		finally {
			releasing = false;
		}
	}

 

 

 

 

两个版本中的closeStatements方法不同,3.2.7中加了对ConcurrentModificationException的处理,当遇到这个异常时,就break,这样就不会再循环打印这个错误了。

 

查了一下jboss下的hibernate3.jar,这个包使用的是3.2.4版本的,如果修改这个错误,升级一下hibernate的版本即可。

另一个问题,商用上有两台内容服务器,部署的包一样,而环境也是一样(没认真检查),两台机都有打包电子书的操作,为什么一台机会循环打印日志,而另一台则不会呢?

认真看看hibernate3.2.7中加了对ConcurrentModificationException处理的注释:

大概意思是:这只会在很小概率下发生的,当用上事务管理和事务超时时,事务超时会通过hibernate已注册事务同步的一个单独线程进行回调,这时候这个单独的线程通过这段时间再执行任务,而同时应用的主线程也在执行,这样我们就会陷入一种像日冕物质抛射的状况,尽管这个本身就是不允许的,如果我们不采取措施处理这个问题,最终结果就是一个无止境的循环。。。

 

 

这里提及到事务超时,这里想起了内容1和内容2两台服务器,一台的日志暴涨,一台却不会,后台查一下是jboss的事务超时时间不同,内容1的是好几个小时,而内容2的是5分钟,应该跟这个有关系了。

 

 

解决方法:更换hibernate的版本和修改jboss的事务超时时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值