Scott Marlow wrote:
Adrian wrote:
> On Wed, 2007-07-11 at 11:58 -0400, Scott Marlow wrote:
>
>> Hi Adrian,
>>
>> The 2-3 second contention that I'm seeing is on the following call stack:
>>
>> "PooledInvokerThread-192.169.1.2: java.util.Hashtable.get :335
>> PooledInvokerThread-192.169.1.2: org.jnp.interfaces.NamingContext.useAbsoluteName
:1090
>> PooledInvokerThread-192.169.1.2:
org.jnp.interfaces.NamingContext.getObjectInstance :1123
>> PooledInvokerThread-192.169.1.2:
org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure :1142
>> PooledInvokerThread-192.169.1.2: org.jnp.interfaces.NamingContext.lookup :705
>> PooledInvokerThread-192.169.1.2: org.jnp.interfaces.NamingContext.lookup :587
>> PooledInvokerThread-192.169.1.2: javax.naming.InitialContext.lookup :351
>> PooledInvokerThread-192.169.1.2:
org.hibernate.transaction.JTATransactionFactory.isTransactionInProgress :83
>> PooledInvokerThread-192.169.1.2:
org.hibernate.jdbc.JDBCContext.isTransactionInProgress :180
>> PooledInvokerThread-192.169.1.2:
org.hibernate.jdbc.JDBCContext.registerSynchronizationIfPossib :158
>> PooledInvokerThread-192.169.1.2:
org.hibernate.impl.SessionImpl.checkTransactionSynchStatus :1850
>> PooledInvokerThread-192.169.1.2: org.hibernate.impl.SessionImpl.getEntityMode
:1274
>> PooledInvokerThread-192.169.1.2:
org.hibernate.engine.StatefulPersistenceContext.addEntry :415
>> PooledInvokerThread-192.169.1.2:
org.hibernate.engine.StatefulPersistenceContext.addEntity :382
>> PooledInvokerThread-192.169.1.2:
org.hibernate.engine.TwoPhaseLoad.addUninitializedEntity :240
>> PooledInvokerThread-192.169.1.2: org.hibernate.loader.Loader.loadFromResultSet
:1358
>> PooledInvokerThread-192.169.1.2: org.hibernate.loader.Loader.instanceNotYetLoaded
:1300
>> PooledInvokerThread-192.169.1.2: org.hibernate.loader.Loader.getRow :1197
>> ..."
>>
>>
>> I am looking at changing the Hashtable to a ConcurrentHashMap which
>> could help some applications run more concurrently.
>>
>
> This just looks like a bug in Hibernate.
>
> It is caching the naming context in the JTATransactionFactory
> and then using it concurrently across threads, without
> the required synchronization.
>
> This probably only works by luck, because it is looking up in
> "java:comp" for the UserTransaction which is a read only context
> constructed at deployment time and is therefore unlikely
> to have concurrency problems.
>
> I'm sure if this class was changed to create a new initial context
> for each request you wouldn't see the contention, but that
> might not be very efficient either. Depends how often the
> isTransactionInProgress() is invoked.
>
> I don't see why it isn't caching the UserTransaction instead anyway.
> It's probably because some people use Hibernate across transaction
> demarcation boundaries in at least dubious, if not broken ways.
Hibernate does offer a few alternatives to the JTATransactionFactory
(applications can also implement their own
org.hibernate.transaction.TransactionFactory solution). There is a
JDBC based implementation that shouldn't have this problem. There is
also a CMT solution that also shouldn't hit this problem (it caches a
transactionmanager.)
I'll try caching the UserTransaction in the Hibernate
JTATransactionFactory.
I tried caching the UserTransaction and that eliminated the contention.
I owe you a pint the next time you visit!
Thanks,
Scott