Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 333316 - Locked SE thread during ConcurrencyManager.acquire() in custom toString() on LAZY IndirectList @OneToMany field
Summary: Locked SE thread during ConcurrencyManager.acquire() in custom toString() on ...
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 7
: P4 minor with 2 votes (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard: concurrency
Keywords:
Depends on:
Blocks: 455043
  Show dependency tree
 
Reported: 2010-12-29 15:46 EST by Michael OBrien CLA
Modified: 2022-06-09 10:28 EDT (History)
4 users (show)

See Also:


Attachments
SE Eclipse 3.5 JPA project reproduction and model (105.88 KB, application/x-zip-compressed)
2010-12-29 15:49 EST, Michael OBrien CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michael OBrien CLA 2010-12-29 15:46:54 EST
>An SE application hangs indefinitely trying to acquire the lock during a toString() on a LAZY list.
>The following code locks when the custom toString() is invoked during a debug session in Eclipse or is printed to the console

ConcurrencyManager.java:
  public synchronized void acquire(boolean forMerge) throws ConcurrencyException {
>    while (((this.activeThread != null) || (this.numberOfReaders > 0)) && (this.activeThread != Thread.currentThread())) {

>because of the client code
    public String toString() {...
>        for(Processor<P> processor : processors) { // this for:each loop may hang on an indirectList for LAZY fetchType

@Entity
public class HyperCube<P> extends ComputeFabric implements Serializable {
...
    // LAZY will hang on 3+ entries during a toString() if a resultList is instantiated from a query via debugging or iteration
    @OneToMany(mappedBy="hyperCube", cascade=CascadeType.ALL, fetch=FetchType.LAZY)//.EAGER)
    private List<Processor<P>> processors;


>Forensics: Use JConsole.exe and navigate to the threads tab - select the main thread for SE

ConcurrencyManager.java
    public synchronized void acquire(boolean forMerge) throws ConcurrencyException {
        while (((this.activeThread != null) || (this.numberOfReaders > 0)) && (this.activeThread != Thread.currentThread())) {
            // This must be in a while as multiple threads may be released, or another thread may rush the acquire after one is released.
            try {
                this.numberOfWritersWaiting++;
>93:            wait();


Name: main
State: WAITING on org.eclipse.persistence.internal.helper.ConcurrencyManager@1072b90
Total blocked: 0  Total waited: 1

Stack trace: 
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
org.eclipse.persistence.internal.helper.ConcurrencyManager.acquire(ConcurrencyManager.java:93)
org.eclipse.persistence.internal.identitymaps.CacheKey.acquire(CacheKey.java:126)
org.eclipse.persistence.internal.identitymaps.AbstractIdentityMap.acquireLock(AbstractIdentityMap.java:120)
org.eclipse.persistence.internal.identitymaps.IdentityMapManager.acquireLock(IdentityMapManager.java:144)
org.eclipse.persistence.internal.sessions.IdentityMapAccessor.acquireLock(IdentityMapAccessor.java:92)
org.eclipse.persistence.internal.sessions.IdentityMapAccessor.acquireLock(IdentityMapAccessor.java:83)
org.eclipse.persistence.internal.sessions.AbstractSession.retrieveCacheKey(AbstractSession.java:4556)
org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:665)
org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:496)
org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectsInto(ObjectBuilder.java:975)
org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:426)
org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1080)
org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:808)
org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1040)
org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:383)
org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:2789)
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1508)
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1490)
org.eclipse.persistence.internal.indirection.QueryBasedValueHolder.instantiate(QueryBasedValueHolder.java:98)
org.eclipse.persistence.internal.indirection.QueryBasedValueHolder.instantiate(QueryBasedValueHolder.java:88)
org.eclipse.persistence.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:88)
   - locked org.eclipse.persistence.internal.indirection.QueryBasedValueHolder@21c3b0
org.eclipse.persistence.indirection.IndirectList.buildDelegate(IndirectList.java:237)
org.eclipse.persistence.indirection.IndirectList.getDelegate(IndirectList.java:397)
   - locked org.eclipse.persistence.indirection.IndirectList@b69467
org.eclipse.persistence.indirection.IndirectList$1.<init>(IndirectList.java:525)
org.eclipse.persistence.indirection.IndirectList.listIterator(IndirectList.java:524)
org.eclipse.persistence.indirection.IndirectList.iterator(IndirectList.java:488)
org.eclipse.persistence.example.jpa.dataparallel.model.HyperCube.toString(HyperCube.java:269)
java.text.MessageFormat.subformat(MessageFormat.java:1246)
java.text.MessageFormat.format(MessageFormat.java:836)
java.text.Format.format(Format.java:140)
java.text.MessageFormat.format(MessageFormat.java:812)
org.eclipse.persistence.internal.localization.EclipseLinkLocalization.buildMessage(EclipseLinkLocalization.java:77)
org.eclipse.persistence.internal.localization.TraceLocalization.buildMessage(TraceLocalization.java:30)
org.eclipse.persistence.logging.AbstractSessionLog.formatMessage(AbstractSessionLog.java:852)
org.eclipse.persistence.logging.DefaultSessionLog.log(DefaultSessionLog.java:156)
   - locked org.eclipse.persistence.logging.DefaultSessionLog@c907ff
org.eclipse.persistence.internal.sessions.AbstractSession.log(AbstractSession.java:3058)
org.eclipse.persistence.internal.sessions.AbstractSession.log(AbstractSession.java:4174)
org.eclipse.persistence.internal.sessions.AbstractSession.log(AbstractSession.java:4146)
org.eclipse.persistence.internal.sessions.AbstractSession.log(AbstractSession.java:4122)
org.eclipse.persistence.internal.sessions.AbstractSession.log(AbstractSession.java:4044)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.logDebugMessage(UnitOfWorkImpl.java:5475)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3856)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3826)
org.eclipse.persistence.mappings.ObjectReferenceMapping.buildUnitofWorkCloneForPartObject(ObjectReferenceMapping.java:100)
org.eclipse.persistence.mappings.ObjectReferenceMapping.buildCloneForPartObject(ObjectReferenceMapping.java:74)
org.eclipse.persistence.internal.indirection.NoIndirectionPolicy.cloneAttribute(NoIndirectionPolicy.java:76)
org.eclipse.persistence.mappings.ForeignReferenceMapping.buildClone(ForeignReferenceMapping.java:250)
org.eclipse.persistence.internal.descriptors.ObjectBuilder.populateAttributesForClone(ObjectBuilder.java:3273)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.populateAndRegisterObject(UnitOfWorkImpl.java:3622)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:987)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:916)
org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(UnitOfWorkIdentityMapAccessor.java:181)
org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getFromIdentityMap(UnitOfWorkIdentityMapAccessor.java:120)
org.eclipse.persistence.internal.sessions.IdentityMapAccessor.getFromIdentityMap(IdentityMapAccessor.java:367)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3868)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3826)
org.eclipse.persistence.mappings.ObjectReferenceMapping.buildUnitofWorkCloneForPartObject(ObjectReferenceMapping.java:100)
org.eclipse.persistence.mappings.ObjectReferenceMapping.buildCloneForPartObject(ObjectReferenceMapping.java:74)
org.eclipse.persistence.internal.indirection.NoIndirectionPolicy.cloneAttribute(NoIndirectionPolicy.java:76)
org.eclipse.persistence.mappings.ForeignReferenceMapping.buildClone(ForeignReferenceMapping.java:250)
org.eclipse.persistence.internal.descriptors.ObjectBuilder.populateAttributesForClone(ObjectBuilder.java:3273)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.populateAndRegisterObject(UnitOfWorkImpl.java:3622)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:987)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:916)
org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(UnitOfWorkIdentityMapAccessor.java:181)
org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getFromIdentityMap(UnitOfWorkIdentityMapAccessor.java:120)
org.eclipse.persistence.internal.sessions.IdentityMapAccessor.getFromIdentityMap(IdentityMapAccessor.java:367)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3868)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3826)
org.eclipse.persistence.mappings.ObjectReferenceMapping.buildUnitofWorkCloneForPartObject(ObjectReferenceMapping.java:100)
org.eclipse.persistence.mappings.ObjectReferenceMapping.buildCloneForPartObject(ObjectReferenceMapping.java:74)
org.eclipse.persistence.internal.indirection.NoIndirectionPolicy.cloneAttribute(NoIndirectionPolicy.java:76)
org.eclipse.persistence.mappings.ForeignReferenceMapping.buildClone(ForeignReferenceMapping.java:250)
org.eclipse.persistence.internal.descriptors.ObjectBuilder.populateAttributesForClone(ObjectBuilder.java:3273)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.populateAndRegisterObject(UnitOfWorkImpl.java:3622)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:987)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:916)
org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(UnitOfWorkIdentityMapAccessor.java:181)
org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getFromIdentityMap(UnitOfWorkIdentityMapAccessor.java:120)
org.eclipse.persistence.internal.sessions.IdentityMapAccessor.getFromIdentityMap(IdentityMapAccessor.java:367)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3868)
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3826)
org.eclipse.persistence.mappings.CollectionMapping.buildElementUnitOfWorkClone(CollectionMapping.java:265)
org.eclipse.persistence.mappings.CollectionMapping.buildElementClone(CollectionMapping.java:277)
org.eclipse.persistence.internal.queries.ContainerPolicy.addNextValueFromIteratorInto(ContainerPolicy.java:210)
org.eclipse.persistence.mappings.CollectionMapping.buildCloneForPartObject(CollectionMapping.java:203)
org.eclipse.persistence.internal.indirection.UnitOfWorkQueryValueHolder.buildCloneFor(UnitOfWorkQueryValueHolder.java:51)
org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiateImpl(UnitOfWorkValueHolder.java:161)
org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiate(UnitOfWorkValueHolder.java:222)
org.eclipse.persistence.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:88)
   - locked org.eclipse.persistence.internal.indirection.UnitOfWorkQueryValueHolder@2bf6c0
org.eclipse.persistence.indirection.IndirectList.buildDelegate(IndirectList.java:237)
org.eclipse.persistence.indirection.IndirectList.getDelegate(IndirectList.java:397)
   - locked org.eclipse.persistence.indirection.IndirectList@54be84
org.eclipse.persistence.indirection.IndirectList$1.<init>(IndirectList.java:525)
org.eclipse.persistence.indirection.IndirectList.listIterator(IndirectList.java:524)
org.eclipse.persistence.indirection.IndirectList.iterator(IndirectList.java:488)
org.eclipse.persistence.example.jpa.dataparallel.model.HyperCube.toString(HyperCube.java:269)
java.lang.String.valueOf(String.java:2826)
java.lang.StringBuilder.append(StringBuilder.java:115)
org.eclipse.persistence.example.dataparallel.GridClient.queryComparisonViaNamedQuery(GridClient.java:236)
org.eclipse.persistence.example.dataparallel.GridClient.demo(GridClient.java:266)
org.eclipse.persistence.example.dataparallel.GridClient.main(GridClient.java:373)


Name: Finalizer
State: WAITING on java.lang.ref.ReferenceQueue$Lock@9b6976
Total blocked: 96  Total waited: 91

Stack trace: 
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)


>Workaround:
- change to FetchType.EAGER
- or, remove custom toString() that does a for:each on the indirect list
Comment 1 Michael OBrien CLA 2010-12-29 15:49:02 EST
Created attachment 185891 [details]
SE Eclipse 3.5 JPA project reproduction and model
Comment 2 Michael OBrien CLA 2010-12-29 16:03:32 EST
>Essentially, this issue occurs if we trigger indirect instantiation by printing LAZY relationships while debugging or in a println()
If we toString() a simpler flat representation of the entity we are OK
Comment 3 Michael OBrien CLA 2010-12-29 16:08:43 EST
>3rd option) use
        if(!(processors instanceof IndirectList)) {  // from core
            for(Processor<P> processor : processors) { // this for:each loop may hang on an indirectList for LAZY fetchType
Comment 4 Michael OBrien CLA 2011-01-04 10:30:00 EST
>Discussed this with team
Was a previously known issues - we don't know which side of the relationship will lock first. 

>reproduction of this obscure use-case was
A bidirectional @OneToMany mixed LAZY/EAGER relationship is debugged on the OneToMany inverse side when the collection is still lazy (uninstantiated = IndirectList)

public class HyperCube<P> extends ComputeFabric implements Serializable {
    // Inverse side
    @OneToMany(mappedBy="hyperCube", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    private List<Processor<P>> processors;
...
}
public class Processor<P> implements Serializable {
    // owning side
    @ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    private HyperCube<P> hyperCube;


>We will likely no fix this one.
Comment 5 Michael OBrien CLA 2011-01-04 14:55:46 EST
>Similar reference bugs (we need to triage whether any of them are related)
Looks like only bug # 309822 may be related (interaction with the lazy IndirectList)
bug# 309822 Deadlock when returning Entities from a remote method call 
bug# 312110 NoWait locking code continues to wait on ReadLock (fixed)
bug# 312462 ConcurrencyManager.acquire() hangs forever (fixed) dup of Bug# 312110
- discovered RT newgroup posting relating to bug# 309822 that is a usefull alternate reproduction reference.
Comment 6 Eclipse Webmaster CLA 2022-06-09 10:14:34 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink
Comment 7 Eclipse Webmaster CLA 2022-06-09 10:28:48 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink