Comments 18
возможно, что ошибка совсем не в вашем коде, а в сторонней библиотеке
Э, ну мы как-то после полугода разборок, смены трех или четырех версий Java, дорылись силами поддержки Оракла и своими до бага в ядре линукс. Типа, Один из вариантов mutex плохо работал.
Почему нельзя было воспроизвести у себя и посмотреть?
Потому что данный тип исключения с циклической ссылкой генерировался библиотекой Apache VFS в очень специфическом случае — когда upload файла фейлился на OutputStream.close(). В остальных случаях, когда соединение рвалось на OutputStream.write(), в т.ч. и на интеграционных тестах, все отрабатывало без проблем. В то время у клиента по ночам возникали проблемы с инфраструктурой, и данный баг время от времени редко, но вылезал.
(по моему – в Apache VFS, но хорошо было бы увидеть исправление в нём и защиту от таких багов в Logback)
Если глобально, то в дизайне IO-стримов в Java. А конкретно этом случае виноват Logback. В Java нигде не говорится, что циклические ссылки невозможны или некорректны. Она не дает создать только прямую ссылку на само исключение через ex.addSuppressed(ex), а транзитивные возможны. К тому же остальные логгеры отрабатывают корректно.
Apache VFS в случае, если рвалась сессия SFTP, кешировал это исключение и кидал его на все последующие вызовы write(), что впринципе корректно. Но поскольку в close() Apache VFS еще производил запись (типа установить атрибуты удаленного файла), то в случае ошибки блок try-with-resources добавлял к suppressed то же самое закешированное исключение, что вызывало цикличность. Как-то так.
P.S. Вот Apache VFS реально плохо задизайнена. Там дофига подводных камней, один из которых — привязка ресурсов к ThreadLocal. То есть если вы открываете ресурс в одном треде, пишите или закрываете в другом, то у вас происходит утечка памяти, которая в нашем случае стабильно приводила к OutOfMemoryError.
Из подобных мистических историй но уровнем загадочности полегче припомнилось:
Задача планировщика так же останавливалась в try-catch блоке, при этом проходя мимо всех catch и finally. Но здесь было проще догадаться: как оказалось, задача где-то у себя очень глубоко (где не ожидалось) открывала http соединение, и вечно ждало ответа, хотя физически соединение было прервано (даже от сети отключали, исключение не выпадало)
Ещё более лёгкая на догадки проблема была связана с некорректной велосипедной реализацией пула в части синхронизации, ошибка похожая на ленивый синглтон в котором отсутствует блок синхронизации, в результате которой утекали зомби, оставшиеся без нужных ссылок (случайно заменены заместителями делающими их работу), ничего не делающие, но висящие в памяти и активно мешающие.
А по топику: это не просто баг, это "удачный" союз двух багов, и я даже не знаю, какой из них более некорректный — рекурсивный стектрейс или не ожидание рекурсии в этом моменте.
Но, имхо, давно висящий тикет для библиотеки такого уровня, при предположении, что ситуация там не авральная — это халатность
Да можно подумать сторонние библиотеки пишут единороги с крыльями…
Разбираясь в коде jdbc thin драйвере Oracle просто поражался степени лапшеватости и корявости его кода.
jdbc драйвер кидал пустое(!) RuntimeException при возникновении проблем маппинга структур java на структуры Oracle.
Всегда нужно быть готовым к подобным проблемам.
Хибернейт у меня до сих пор оставляет некий осадок от использования. И некорректный sql тоже был. Из недавнего — в тестах, когда тест запускается внутри одной единственной транзакции с Rollback аннотацией над тестовым методом при транзакционной вложенности в тестируемых сервисах хибернейт теряет дочерние сущности. Вроде как и баг хибернейта, но руки не дошли докопаться до истины
У меня тоже с хибернейтом не сложилось. Известны случаи, где он генерит семантически неправильный SQL, иногда делает странные сторонние вещи, когда его не просят, причем в зависимости от движка базы, до последнего времени криво поддерживал EntityGraph, и после перехода на ByteBuddy стал неимоверно долго стартовать. Поэтому я уже привык использовать EclipseLink.
Ваша ошибка в неиспользовании блока finally.
Но как оказалось, до меня уже раскопали.
www.saschahlusiak.de/2018/10/selector-select-returns-0-immediately
Печаль в том, что этот баг находится в sun.nio.ch.PollSelectorImpl Java 8, и Android его не особо спешить исправить…
Данная баг фича все еще присутствует в последней версии библиотеки.
Лицензия свободная. Так, исправьте и сделайте PR, кто вам мешает?
Ну вот например: планировщик заданий «enterprise» (как они себя называют) уровня.
github.com/quartz-scheduler/quartz/issues
176 issues (225 закрыто)
38 висящих пулл-реквестов
28 contributor-ов
Последний релиз — год назад.
При активной эксплуатации нашёлся редкий баг, и вряд ли кто будет его чинить — у всех-то нормально работает.
В учебных заведениях нужно доносить мысль, что open-source — это не «бесплатно скачал и пользуйся», а никто ничего тебе не должен. И при выборе библиотеки нужно взвешивать затраты между поддерживаемым платным ПО и затратами на самостоятельное допиливание «бесплатного» ПО.
Чтобы потом не разочаровываться.
Что .jar сторонний нам готовил…