GUILLEMOT commented on Bug HHH-7867

We encoutered 2 stacktraces with the same cause :

The Map.Entry returned by IdentityMap.concurrentEntries, which call IdentityMap.entryArray has a potential bug :

  • result array is created from map size
  • but filled with entrySet.size

It happens that entrySet.size and map size are not the same (normal according to javadoc, entrySet is constant for an iteration)

My use case is the following (with EJB 3.1, JBoss AS 7.1.1 container) :
calling transaction (public method of my EJB)

  • load objects
  • multithread tasks that use objects
  • wait for end tasks
  • find in database (which makes the flush call)

But I don't realy understand why in my own transaction, the persistenceContext.getEntityEntries() map evolve... after the multithread tasks I'm back in a single transaction.

In any case to avoid this, build the array with entrySet.size instead of map.size seems a better solution.
In my own use case, I'll try to find why persistenceContext.getEntityEntries() evolve or try to patch hibernate to test this.

Here is IdentityMap.entryArray source code form 4.1.7, (seems same in 4.2.2).

@SuppressWarnings(

{"unchecked"}

)
public Map.Entry[] entryArray() {
if (dirty) {
entryArray = new Map.Entry[ map.size() ];
Iterator itr = map.entrySet().iterator();
int i=0;
while ( itr.hasNext() )

{ Map.Entry me = (Map.Entry) itr.next(); entryArray[i++] = new IdentityMapEntry( ( (IdentityKey) me.getKey() ).key, me.getValue() ); }

dirty = false;
}
return entryArray;
}

The stacktraces :
1)
Caused by: java.lang.NullPointerException: null
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:148) ~[hibernate-core-4.1.7.Final.jar!/:4.1.7.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88) ~[hibernate-core-4.1.7.Final.jar!/:4.1.7.Final]
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58) ~[hibernate-core-4.1.7.Final.jar!/:4.1.7.Final]
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1182) ~[hibernate-core-4.1.7.Final.jar!/:4.1.7.Final]
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1237) ~[hibernate-core-4.1.7.Final.jar!/:4.1.7.Final]
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) ~[hibernate-core-4.1.7.Final.jar!/:4.1.7.Final]
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:257) ~[hibernate-entitymanager-4.1.7.Final.jar!/:4.1.7.Final]

2)
Caused by: java.lang.NullPointerException
at org.hibernate.event.internal.AbstractLockUpgradeEventListener.upgradeLock(AbstractLockUpgradeEventListener.java:61) [hibernate-core-4.1.7.Final.jar:4.1.7.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromSessionCache(DefaultLoadEventListener.java:512) [hibernate-core-4.1.7.Final.jar:4.1.7.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:404) [hibernate-core-4.1.7.Final.jar:4.1.7.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:204) [hibernate-core-4.1.7.Final.jar:4.1.7.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:143) [hibernate-core-4.1.7.Final.jar:4.1.7.Final]

This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira