суббота, 19 июля 2014 г.

Кэширование опасно

Попал ко мне баг в IDEA, что popup в диалогах глючит: открывается иногда под диалогом и нелепого размера.

Я разобрался, что это из-за кеширования popup-окон в PopupFactory. Во-первых, кэширование проиходит по WindowAccessor, который, будучи вызванным на окне или диалоге, возвращает не себя самого, как хотелось бы, а окно, в зависимости от которого оно было вызвано. А во-вторых, закэшированный объект инициализируется методом reset класса Popup, который (внимание!) не меняет owner, если тот уже установлен.

Я это исправил таким образом, что если IDEA запрашивает показ popup для окна, то я передаю в JDK не само окно, а его первый компонент, чтобы обойти проблему ключа кэширования. Теперь я уверен, что для каждого окна вернётся popup завязанный именно на него, а не на его владельца. Надо бы выставить баг на JDK...

Но это изменение породило кучу проблем, причём у меня под Windows их не просто поймать, а линуксоиды натыкаются на них постоянно. Теперь popup глючит в основном окне: его размеры схлапываются в ноль и он показывается только со второго раза.

Вчера убил на решение проблемы целый день. Тяжело, когда воспроизводится не у тебя, а у коллег, которые сильно заняты. По пути к метро с одним из коллег обсуждал проблему, а потом долго не мог заснуть. Часа в три, когда Юля покормила Катюшу, оставил её спать, а сам пошёл ребёнка укачивать и... с Катей на руках просидел за компьютером до 7 утра.

Проблема оказалась всё в том же кэшировании. Пользовательский компонент добавляется в окно с установленным BorderLayout. Предполагается, что он там его заменит, но на самом деле в JDK есть багофича, что в самом BorderLayout компонент действительно заменяется, но в окне становится уже два компонента. Это каким-то образом влияет на отрисовку. Я пока не стал разбираться каким, так как написал простой фикс, где после создания popup удаляю из контейнера моего компонента все остальные компоненты. Именно это должны делать в JDK в тот момент, когда кладут объект в кэш.

В понедельник проверю фикс на коллегах...

PS. Судя по тому, что в код JDK 9 добавили возможность запрета кэширования, не одни мы натыкались на эту проблему, но ребята решили не пофиксить найденные мной сейчас баги, а просто отрубить кэширование совсем.

1 комментарий:

  1. Как оказалось, для проблемы с cached popups уже есть workaround в IDEA. Но я нашёл ещё один кэш!

    Похоже, что окно кэширует preferred size то ли в своём peer, то ли в content pane. И при новом отображении показывает именно его.

    ОтветитьУдалить