[
https://jira.jboss.org/jira/browse/JBSEAM-2973?page=com.atlassian.jira.pl...
]
Torsten Fink commented on JBSEAM-2973:
--------------------------------------
We probably stumbled over the same issue.
Our application had to survive a night with full load. On the next morning the heap was
full of JbpmContext's. After looking at the source code of Seam and at the debug
messages we came up with this hypothesis:
* The SFSB EjbSynchronizations is placed in the event context, the
Seam-JbpmContext-Component also lives in the event context.
* Using EJB transactions, EjbSynchronizations is responsible for cleaning up the
JbpmContext after the end of the transaction.
* Unfortunately the event context ends BEFORE EjbSynchronizations has the chance to clean
up the JbpmContext.
Using BMT the transaction ends before the event context ends. Thus, the JbpmContext is
cleaned up.
We switch all our MDBs, EJB-timers, and Web-services from CMT to BMT and (after fixing
some other leaks, e.g. a class loader issue in jBpm), we survived the night.
I wrote a small test application that shows the memory leak, but I do not find a
possibility to attach the archive. I uploaded the application to my personal account. You
can find it here:
http://public.me.com/torsten.fink/
The name of the archive is "MemoryLeakEventKontext.tgz".
It is a Maven application that consists of
- a Web-GUI to start the test and displays the results
- a SFSB that sends 10 messages each to two queues (the standard queues A and B), waits a
little bit, and does a gc
- two MDBs, one with CMT, one with BMT, which uses Seam injection to access a
jBpm-Context
- an application scoped POJO that saves the contexts in a Set using a weak reference
After executing the tests and the GC, the surviving references are displayed. You can see
that the CMT references are not gs'ed whereas the BMT references are cleaned up.
EjbSynchronisations are destroyed before afterCompletion call
-------------------------------------------------------------
Key: JBSEAM-2973
URL:
https://jira.jboss.org/jira/browse/JBSEAM-2973
Project: Seam
Issue Type: Bug
Components: Core
Affects Versions: 2.0.1.GA
Environment: JBOSS4.2.2GA
Reporter: stefan meyer
Assignee: Pete Muir
Fix For: 2.1.0.BETA1
http://www.seamframework.org/Community/EjbSynchronisationsAfterCompletion...
I use an MDB. The EJBSynchronisations.registerSynchronisation are called by
MangedPersistenceContext and ManagedJbpmContext. Thus creating 3
Synchronisation-Registration on the UserTransaction (first once is created by creating the
ejb or maybe calling the create-method - dont know exactly). At some point the
EJBSychronisations will be destroyed since they are stateful. Seam destroys them when
calling Lifecycle.endCall and destroying the Contexts. The destruction will create another
TransactionSynchronisation implemented by the StatefulRemoveInterceptor from Jboss. The
beforeCompletion will be called in the order the synchronisations were registered. The
afterCompletion will be called in the reverse order. The StatefulRemoveInterceptor is
first and removes the EjbYnchronisation from the cache (whatever that is). The other calls
fail because the ejb container cannot find them.
My ugly workaround is to force a different order calling create and destroy of
EJBSynchronisations upon entering the MDB. This leads to only one failure - the very first
Synchronisations.
Reproducing this problem should be very straight forward. Just call an MDB and do
sonething with the seam managed entityManager.
Another bug closely related is that ManagedPersistenceContext.afterCompletion calls
close. and in close it unsuccessfully tries to get a hold of the transaction component
(Transaction.instance) - the contexts are gone already.
here is the critical code (Please see the comment in afterCompletion):
public void afterCompletion(int status)
{
synchronizationRegistered = false;
//if ( !Contexts.isConversationContextActive() )
if (destroyed)
{
//in calls to MDBs and remote calls to SBs, the
//transaction doesn't commit until after contexts
//are destroyed, so wait until the transaction
//completes before closing the session
//on the other hand, if we still have an active
//conversation context, leave it open
close();
}
}
private void close()
{
boolean transactionActive = false;
try
{
transactionActive = Transaction.instance().isActive();
}
catch (SystemException se)
{
log.debug("could not get transaction status while destroying persistence
context");
}
if ( transactionActive )
{
throw new IllegalStateException("attempting to destroy the persistence
context while an active transaction exists (try installing
<transaction:ejb-transaction/>)");
}
if ( log.isDebugEnabled() )
{
log.debug("destroying seam managed persistence context for persistence
unit: " + persistenceUnitJndiName);
}
if (entityManager!=null)
{
entityManager.close();
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira