[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-5599) NPE occurs when using Infinispan as L2 Cache

Brian Stansberry (JIRA) noreply at atlassian.com
Mon Oct 18 20:49:49 EDT 2010


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-5599?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=38796#action_38796 ] 

Brian Stansberry commented on HHH-5599:
---------------------------------------

I think this is the correct fix:

### Eclipse Workspace Patch 1.0
#P hibernate-infinispan
Index: src/main/java/org/hibernate/cache/infinispan/access/PutFromLoadValidator.java
===================================================================
--- src/main/java/org/hibernate/cache/infinispan/access/PutFromLoadValidator.java	(revision 20852)
+++ src/main/java/org/hibernate/cache/infinispan/access/PutFromLoadValidator.java	(working copy)
@@ -266,7 +266,7 @@
       PendingPutMap pending = pendingPuts.get(key);
       if (pending != null) {
          if (pending.size() == 0) {
-            pendingPuts.remove(key);
+            pendingPuts.remove(key, pending);
          }
          pending.releaseLock();
       }
@@ -560,11 +560,13 @@
             if (map.acquireLock(100, TimeUnit.MILLISECONDS)) {
                try {
                   PendingPut cleaned = map.remove(toClean.owner);
-                  if (toClean.equals(cleaned) == false) {
-                     // Oops. Restore it.
-                     map.put(cleaned);
+                  if (toClean.equals(cleaned) == false) {                     
+                     if (cleaned != null) {
+                    	// Oops. Restore it.
+                        map.put(cleaned);
+                     }
                   } else if (map.size() == 0) {
-                     pendingPuts.remove(toClean.key);
+                     pendingPuts.remove(toClean.key, map);
                   }
                }
                finally {


The changes to pendingPuts.remove are not directly related to this issue; just I think they are the right thing to do.

What's happening is a race to the PendingPutMap lock between a thread cleaning an "outdated" pending put and either another thread doing the same, or the put itself coming in and cleaning it. For the losing thread, PendingPut cleaned = map.remove(toClean.owner); is returning null, since the winning thread already did the removal.

> NPE occurs when using Infinispan as L2 Cache
> --------------------------------------------
>
>                 Key: HHH-5599
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5599
>             Project: Hibernate Core
>          Issue Type: Bug
>          Components: caching (L2)
>    Affects Versions: 3.5.5, 3.5.6
>         Environment: Hib 3.5.6
> Infinispan 4.2.0.ALPHA2
> (same thing happen with Hib 3.5.5 and IS 4.1.0.FINAL)
>            Reporter: Chris
>            Assignee: Galder Zamarreno
>            Priority: Critical
>
> Pretty much randomly or so it seems, infinispan hibernate layer will throw a NPE. It occurs a lot when the j2EE server is started and overtime (once caches are warmer?) diminish.
> The issue comes from the PutFromLoadValidator.Java(565).The cleaned element is null and the map.put(cleaned) fails since the key is coming from the cleaned element (cleaned.owner).
> Complete stacktraces, the first on entity loading and the later on collection loading:
> Cause: java.lang.NullPointerException
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator$PendingPut.access$700(PutFromLoadValidator.java:674)
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator$PendingPutMap.put(PutFromLoadValidator.java:627)
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator.cleanOutdatedPendingPuts(PutFromLoadValidator.java:565)
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator.preventOutdatedPendingPuts(PutFromLoadValidator.java:493)
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator.registerPendingPut(PutFromLoadValidator.java:438)
>     at org.hibernate.cache.infinispan.access.TransactionalAccessDelegate.get(TransactionalAccessDelegate.java:66)
>     at org.hibernate.cache.infinispan.entity.TransactionalAccess.get(TransactionalAccess.java:36)
>     at org.hibernate.engine.BatchFetchQueue.isCached(BatchFetchQueue.java:278)
>     at org.hibernate.engine.BatchFetchQueue.getEntityBatch(BatchFetchQueue.java:253)
>     at org.hibernate.loader.entity.BatchingEntityLoader.load(BatchingEntityLoader.java:90)
>     at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3270)
>     at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:496)
>     at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:477)
>     at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227)
>     at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285)
>     at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
>     at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
>     at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1028)
>     at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:623)
>     at org.hibernate.type.EntityType.resolve(EntityType.java:431)
>     at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:140)
>     at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:898)
>     at org.hibernate.loader.Loader.doQuery(Loader.java:773)
>     at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
>     at org.hibernate.loader.Loader.loadEntityBatch(Loader.java:2047)
>     at org.hibernate.loader.entity.BatchingEntityLoader.load(BatchingEntityLoader.java:99)
>     at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3270)
>     at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:496)
>     at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:477)
>     at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227)
>     at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285)
>     at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
>     at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
>     at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1028)
>     at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:623)
>     at org.hibernate.type.EntityType.resolve(EntityType.java:431)
>     at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:140)
>     at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:898)
>     at org.hibernate.loader.Loader.doQuery(Loader.java:773)
>     at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
>     at org.hibernate.loader.Loader.doList(Loader.java:2449)
>     at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2192)
>     at org.hibernate.loader.Loader.list(Loader.java:2187)
>     at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
>     at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
>     at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
>     at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
>     at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
> Cause: java.lang.NullPointerException
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator$PendingPut.access$700(PutFromLoadValidator.java:674)
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator$PendingPutMap.put(PutFromLoadValidator.java:627)
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator.cleanOutdatedPendingPuts(PutFromLoadValidator.java:565)
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator.preventOutdatedPendingPuts(PutFromLoadValidator.java:493)
>     at org.hibernate.cache.infinispan.access.PutFromLoadValidator.registerPendingPut(PutFromLoadValidator.java:438)
>     at org.hibernate.cache.infinispan.access.TransactionalAccessDelegate.get(TransactionalAccessDelegate.java:66)
>     at org.hibernate.cache.infinispan.collection.TransactionalAccess.get(TransactionalAccess.java:36)
>     at org.hibernate.engine.BatchFetchQueue.isCached(BatchFetchQueue.java:295)
>     at org.hibernate.engine.BatchFetchQueue.getCollectionBatch(BatchFetchQueue.java:203)
>     at org.hibernate.loader.collection.BatchingCollectionInitializer.initialize(BatchingCollectionInitializer.java:73)
>     at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:628)
>     at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
>     at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1853)
>     at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:479)
>     at org.hibernate.engine.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:899)
>     at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:275)
>     at org.hibernate.loader.Loader.doList(Loader.java:2449)
>     at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2192)
>     at org.hibernate.loader.Loader.list(Loader.java:2187)
>     at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
>     at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
>     at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
>     at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
>     at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
> For now I am masking this class with my own which essentially is a copy and paste but added a null check before trying to put back the element.
> How the big question is : Is it normal that the element can be null and it's a simple null check that has been forgotten or the element should never be null and something bigger is going on ?

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list