Отладка Hibernate / Ehcache тупик - PullRequest
       2

Отладка Hibernate / Ehcache тупик

4 голосов
/ 18 октября 2011

Мы используем Ehcache версии 2.4.4 с Hibernate 3.5.5-FINAL.В моей среде отладки происходит странный случай - похоже, что Ehcache зашел в тупик.Вот соответствующий бит трассировки стека:

http-8080-2@7345 daemon, prio=5, in group 'main', status: 'WAIT'
      at sun.misc.Unsafe.park(Unsafe.java:-1)
      at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:842)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1178)
      at java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock(ReentrantReadWriteLock.java:807)
      at net.sf.ehcache.store.compound.Segment.put(Segment.java:427)
      at net.sf.ehcache.store.compound.CompoundStore.put(CompoundStore.java:141)
      at net.sf.ehcache.Cache.putInternal(Cache.java:1434)
      at net.sf.ehcache.Cache.put(Cache.java:1367)
      at net.sf.ehcache.Cache.put(Cache.java:1339)
      at net.sf.ehcache.constructs.EhcacheDecoratorAdapter.put(EhcacheDecoratorAdapter.java:111)
      at net.sf.ehcache.hibernate.regions.EhcacheTransactionalDataRegion.put(EhcacheTransactionalDataRegion.java:127)
      at net.sf.ehcache.hibernate.strategy.NonStrictReadWriteEhcacheEntityRegionAccessStrategy.putFromLoad(NonStrictReadWriteEhcacheEntityRegionAccessStrategy.java:66)
      at net.sf.ehcache.hibernate.nonstop.NonstopAwareEntityRegionAccessStrategy.putFromLoad(NonstopAwareEntityRegionAccessStrategy.java:180)
      at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:180)
      at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:898)
      at org.hibernate.loader.Loader.doQuery(Loader.java:773)
      at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
      at org.hibernate.loader.Loader.loadEntity(Loader.java:1953)
      at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:86)
      at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:76)
      at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3270)
      at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:496)
      at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:477)
      at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227)
      at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:147)
      at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
      at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:1018)
      at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176)
      at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
      at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:191)
      at vyre.content.items.ItemInfo_$$_javassist_87.equals(ItemInfo_$$_javassist_87.java:-1)
      at org.hibernate.util.EqualsHelper.equals(EqualsHelper.java:33)
      at org.hibernate.type.AbstractType.isEqual(AbstractType.java:132)
      at org.hibernate.type.ComponentType.isEqual(ComponentType.java:153)
      at org.hibernate.cache.CacheKey.equals(CacheKey.java:79)
      at net.sf.ehcache.store.compound.Segment.containsKey(Segment.java:279)
      at net.sf.ehcache.store.compound.CompoundStore.containsKey(CompoundStore.java:353)
      at net.sf.ehcache.store.compound.impl.MemoryOnlyStore.containsKeyInMemory(MemoryOnlyStore.java:121)
      at net.sf.ehcache.Cache.searchInStoreWithStats(Cache.java:1884)
      at net.sf.ehcache.Cache.get(Cache.java:1549)
      at net.sf.ehcache.constructs.EhcacheDecoratorAdapter.get(EhcacheDecoratorAdapter.java:75)
      at net.sf.ehcache.hibernate.regions.EhcacheTransactionalDataRegion.get(EhcacheTransactionalDataRegion.java:105)
      at net.sf.ehcache.hibernate.strategy.NonStrictReadWriteEhcacheEntityRegionAccessStrategy.get(NonStrictReadWriteEhcacheEntityRegionAccessStrategy.java:55)
      at net.sf.ehcache.hibernate.nonstop.NonstopAwareEntityRegionAccessStrategy.get(NonstopAwareEntityRegionAccessStrategy.java:122)
      at org.hibernate.event.def.DefaultLoadEventListener.loadFromSecondLevelCache(DefaultLoadEventListener.java:586)
      at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:459)
      at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227)
      at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:147)
      at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
      at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:1018)
      at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176)
      at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
      at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:191)
      at vyre.content.items.Item_$$_javassist_102.getName(Item_$$_javassist_102.java:-1)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java:-1)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.apache.velocity.runtime.parser.node.PropertyExecutor.execute(PropertyExecutor.java:142)
      at org.apache.velocity.util.introspection.UberspectImpl$VelGetterImpl.invoke(UberspectImpl.java:533)
      at org.apache.velocity.runtime.parser.node.ASTIdentifier.execute(ASTIdentifier.java:198)
      at org.apache.velocity.runtime.parser.node.ASTReference.execute(ASTReference.java:252)
      at org.apache.velocity.runtime.parser.node.ASTReference.render(ASTReference.java:332)
      at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:336)
      at org.apache.velocity.runtime.RuntimeInstance.render(RuntimeInstance.java:1277)
      at org.apache.velocity.runtime.RuntimeInstance.evaluate(RuntimeInstance.java:1216)
      at org.apache.velocity.runtime.RuntimeInstance.evaluate(RuntimeInstance.java:1165)
      at org.apache.velocity.app.Velocity.evaluate(Velocity.java:191)
      at org.apache.jsp.WEB_002dINF.jsp.pub_005fmodule.taglibs.contentTemplate.search.itemLink_jsp._jspService(itemLink.jsp:36)

  (...another hundred or so irrelevant stack trace fragments skipped...)

Вот как я понимаю ситуацию:

  • дно стека начинается там, где Apache Velocity выполняет оценку и передает ейПрокси-объект Hibernate
  • этот объект кэшируется с помощью <cache usage="nonstrict-read-write"/> и имеет составной ключ
  • Hibernate пытается получить объект из кэша
  • Hibernate / Ehcache проверяет равенствообъект (примечание: «реальный» метод equals никогда не выполняется)
  • проверка равенства возвращает false, и объект загружается Hibernate
  • , как только загрузка завершается успешно,объект помещен в кеш
  • тупик?

Фрагмент кода нарушения выглядит следующим образом:

net.sf.ehcache.store.compound.Segment.put(Segment.java:427) 

423 Element put(Object key, int hash, Element element, boolean onlyIfAbsent) { 
424    boolean installed = false; 
425    Object encoded = create(key, element); 
426 
427    writeLock().lock(); 
428    try { 
429       // ensure capacity 
430       if (count + 1 > threshold) { 

Я могу получить доступ к объекту encoded, но похоже, что writeLock() уже получен, и поэтомувся нить застряла.На этом мои силы заканчиваются, так как я очень мало знаю о внутренностях Ehcache Segment.

Кто-нибудь может дать какие-нибудь советы о том, как отладить это дальше?К сожалению, создание небольшого, самосогласованного тестового примера не вариант.

Это также было размещено на странице форумов Ehcache .

Заранее спасибо.

Ответы [ 2 ]

7 голосов
/ 20 октября 2011

Отвечая на мой собственный вопрос на тот случай, если кто-то еще подсунет об этом и сообщение на форумах Ehcache исчезнет.

Причина: Причина взаимоблокировки была в том же потоке, где была сделана попытка найти объект в кеше.В одной из нижних частей стека Ehcache делал readLock().lock() и writeLock().lock() для одного и того же объекта блокировки.Это, очевидно, нет-нет.

Почему это произошло? Это произошло из-за того, что кеш загружал другой объект как побочный эффект (еще одно большое нет-нет), и оба объекта заканчивались водин и тот же сегмент памяти (и, следовательно, разделяет один и тот же ReentrantLock).Подсказка: я использую ту же область кэша, поскольку не хочу указывать емкости для сотен различных типов объектов.

Почему это произошло? Произошла непреднамеренная загрузка при поиске ключа кэша из-замое отображение Hibernate.Объект (который ищется) имел составной ключ, ссылающийся на другой объект.Части этого составного ключа использовались в методе equals и вызывали эту нагрузку.По совпадению, загруженный объект также пытались поместить в тот же сегмент кэша, что привело к тупику.

Извлеченные уроки Будьте экстра осторожнее с вашими отображениями Hibernate.Если у вас есть составной ключ, никогда не используйте <key-many-to-one, так как это может привести к непредсказуемым результатам.Я думаю, что многие люди не осознают этого только потому, что они помещают разные типы объектов в разные области кэша, но непреднамеренные нагрузки, тем не менее, являются злыми.

Все кредиты отправляются Алексу с форумов Терракоты за помощь в выяснении этого.

0 голосов
/ 18 октября 2011

Вы можете использовать JProfiler (есть полнофункциональная ознакомительная версия), чтобы посмотреть текущий график блокировки.Он поддерживает блокировки java.util.concurrent и сообщит вам, у кого есть блокировка и где она была получена.С этой информацией будет легче проанализировать проблему.

Отказ от ответственности: Моя компания разрабатывает JProfiler

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...