As a last resort, AbstractEntityPersister#isTransient calls CacheHelper.fromSharedCache to determine if an entity is cached. If the return value is non-null, then the AbstractEntityPersister#isTransient returns false, and the return value is ignored.
When Infinispan is the cache provider, CacheHelper.fromSharedCache calls InvalidationCacheAccessDelegate#get. If the entity is not already cached, InvalidationCacheAccessDelegate#get adds a pending-put for the entity as a side-effect. The entry in the pending-put map uses a SessionImpl as the map key.
If that entity really is transient, then the pending-put entry never gets cleared until it times out. Since the pending-put map contains SessionImpl keys, those SessionImpl objects cannot be garbage-collected until the entry times out.
If lots of data is in the process of being imported, then an OutOfMemoryError could be thrown. IIUC, it is not recommended to use the cache when importing data. That is why I am calling this issue an "improvement" rather than a "bug". [WFLY-13259|https://issues.redhat.com/browse/WFLY-13259] contains a test that reproduces this issue.
The original proposal was to change AbstractEntityPersister#isTransient to call CachedDomainDataAccess#get. Unfortunately, that would not work consistently. For example, if an entity is deleted, and re-persisted while the deleted entity is still locked in the cache, CachedDomainDataAccess#get will return true, and AbstractEntityPersister#isTransient will incorrectly return false when re-persisting the new entity.
Instead, an improvement would be to not store a SharedSessionContractImplementor in a PendingPut at all.
There is already a way to get a UUID for the session by calling SharedSessionContractImplementor#getSessionIdentifier(). Unfortunately, the implementation in AbstractSharedSessionContract indicates that frequent "UUID generations will cause a significant amount of contention".
Sanne has suggested returning a "token" that is just a new Object. I've created a branch that does this.
Infinispan would need to be updated so that PendingPut#owner is set to SharedSessionContractImplementor#getSessionToken() (instead of the SharedSessionContractImplementor object).