Community
Participate
Working Groups
A deadlock can occur in an object model where classA references classB which references classC, and classC has no relationship mappings. Thread1 attempts to refresh classB and uses joining to bring in classC. Thread2 attempts to modify classA and classC, and sets classA to reference a classB being read in threadA. 1) Thread1 gets deferred lock on ClassB 2) Thread2 gets required locks on classA+classC for updates 3) Thread1 attempts to get active lock on classC, but has to wait as it is held by thread2 4) Thread2 updates, commits, and during the merge tries to get a lock on classB. This causes it to transition to deferred locks. 4b) thread2 attempts to release its deferred lock, causing it to waiting on threadB - a deadlock. Threaddump from such a situation will look similiar to: Thread1: java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000074eb19a00> (a org.eclipse.persistence.internal.helper.ConcurrencyManager) at java.lang.Object.wait(Object.java:485) at org.eclipse.persistence.internal.helper.ConcurrencyManager.acquire(ConcurrencyManager.java:93) - locked <0x000000074eb19a00> (a org.eclipse.persistence.internal.helper.ConcurrencyManager) at org.eclipse.persistence.internal.identitymaps.CacheKey.acquire(CacheKey.java:113) at org.eclipse.persistence.internal.identitymaps.AbstractIdentityMap.acquireLock(AbstractIdentityMap.java:107) at org.eclipse.persistence.internal.identitymaps.IdentityMapManager.acquireLock(IdentityMapManager.java:127) at org.eclipse.persistence.internal.sessions.IdentityMapAccessor.acquireLock(IdentityMapAccessor.java:92) at org.eclipse.persistence.internal.sessions.IdentityMapAccessor.acquireLock(IdentityMapAccessor.java:83) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:698) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:504) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:454) at org.eclipse.persistence.mappings.OneToOneMapping.valueFromRowInternalWithJoin(OneToOneMapping.java:1595) at org.eclipse.persistence.mappings.ForeignReferenceMapping.valueFromRow(ForeignReferenceMapping.java:1737) at org.eclipse.persistence.mappings.DatabaseMapping.readFromRowIntoObject(DatabaseMapping.java:1283) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildAttributesIntoObject(ObjectBuilder.java:342) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:717) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:504) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectsInto(ObjectBuilder.java:910) at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:423) at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1076) at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:740) at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1036) at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:380) at org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:2392) Thread2: java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at org.eclipse.persistence.internal.helper.ConcurrencyManager.releaseDeferredLock(ConcurrencyManager.java:464) at org.eclipse.persistence.internal.identitymaps.CacheKey.releaseDeferredLock(CacheKey.java:348) at org.eclipse.persistence.internal.helper.WriteLockManager.releaseAllAcquiredLocks(WriteLockManager.java:467) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeChangesIntoParent(UnitOfWorkImpl.java:3321) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeClonesAfterCompletion(UnitOfWorkImpl.java:3424) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAfterWriteChanges(UnitOfWorkImpl.java:1245) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commit(UnitOfWorkImpl.java:1081) Multiple threads may look like thread 1, as queries on other threads will end up having to wait for these two threads to release their locks.
Created attachment 184627 [details] proposed fix
Created attachment 184637 [details] revised fix
Created attachment 184890 [details] Core test for the fix
fix was checked into 2.1.2 revision 8635 fix and test patch was checked into 2.2 revision 8679
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink