Бесконечный цикл в java.util.HashMap

У меня здесь очень часто блокируется код Vaadin, и я не знаю, в чем проблема:

Thread 7892: (state = IN_JAVA)
 - java.util.HashMap.getEntry(java.lang.Object) @bci=61, line=349 (Compiled frame; information may be imprecise)
 - java.util.HashMap.containsKey(java.lang.Object) @bci=2, line=335 (Compiled frame)
 - java.util.HashSet.contains(java.lang.Object) @bci=5, line=184 (Compiled frame)
 - com.vaadin.ui.Table.unregisterPropertiesAndComponents(java.util.HashSet, java.util.HashSet) @bci=85, line=1693 (Compiled frame)
 - com.vaadin.ui.Table.refreshRenderedCells() @bci=992, line=1641 (Compiled frame)
 - com.vaadin.ui.Table.valueChange(com.vaadin.data.Property$ValueChangeEvent) @bci=23, line=2897 (Compiled frame)
 - com.vaadin.data.util.IndexedContainer.firePropertyValueChange(com.vaadin.data.util.IndexedContainer$IndexedContainerProperty) @bci=140, line=553 (Compiled frame)
 - com.vaadin.data.util.IndexedContainer.access$1000(com.vaadin.data.util.IndexedContainer, com.vaadin.data.util.IndexedContainer$IndexedContainerProperty) @bci=2, line=64 (Compiled frame)
 - com.vaadin.data.util.IndexedContainer$IndexedContainerProperty.setValue(java.lang.Object) @bci=202, line=915 (Compiled frame)
 - com.aimprosoft.wavilon.backgroundthreads.ChangeCdrThread.insertNewPersonIntoTable(com.aimprosoft.wavilon.model.Person, com.vaadin.ui.HorizontalLayout, com.aimprosoft.wavilon.ui.menuitems.CallContent, com.vaadin.ui.Table) @bci=924, line=208 (Interpreted frame)
 - com.aimprosoft.wavilon.backgroundthreads.ChangeCdrThread$RepaintTableThread.run() @bci=622, line=446 (Compiled frame)

Может кто-нибудь предложить какой-либо способ дальнейшей отладки этой проблемы? Проблема происходит очень редко, и ее довольно сложно воспроизвести.

Ответ 1

Исходя из того, где он находится в коде, единственное объяснение, которое я могу придумать, состоит в том, что есть несколько потоков, которые обращаются к TG40 и обновляют его без надлежащей синхронизации. Это может привести к повреждению структур данных карты и может привести к бесконечному циклу.

Я не могу думать ни о какой другой причине, почему java.util.HashMap.getEntry заблокировался бы. Он не выполняет никакой синхронизации или ввода-вывода.


Роланд Иллиг комментирует:

Номер строки действительно указывает на то, что код зависает в одном из циклов e = e.next.

Это подтверждает мою гипотезу. Конкретная последовательность операций над хеш-таблицей, выполняемая двумя (или более) потоками, привела к созданию цикла/цикла в одной из хеш-цепей. Это повреждение произошло из-за недостаточной синхронизации между потоками, выполняющими операции. Такое случается очень редко, но как только это произойдет, коррупция не исчезнет.

Не углубляясь в исходный код Vaadin, я не могу точно сказать, является ли это ошибкой Vaadin, или ошибкой в том, как вы используете Vaadin. Любое объяснение правдоподобно.

UPDATE

Исходя из этой статьи (предоставленной в комментарии ниже), я бы сказал, что, скорее всего, это проблема в том, как синхронизируется ваше приложение (или нет).

Ответ 2

Итак, вы на самом деле видите здесь поток, идущий в бесконечный цикл, оценивающий e = e.next

В сущности

e.next == e

Это происходит, когда вы кладете в HashMap несколькими потоками во время реструктуризации таблицы.

Взгляните на эту ссылку для получения дополнительной информации

Прекрасное состояние гонки

Чтобы решить эту проблему, используйте либо Collections.synchronizedMap, либо ConcurrentHashMap. Я предлагаю последнее.

Ответ 3

Является ли фоновый поток синхронизированным в экземпляре приложения при изменении компонента? Если нет, то это ваша проблема.