Статический Анализ Потока: Хорошая идея?

Я помогаю поддержать и основываться на довольно большом Swing GUI с большим сложным взаимодействием. Часто я исправляю ошибки, которые являются результатом вещей, входящих в нечетные состояния из-за некоторого состояния состязания где-то в другом месте в коде.

Поскольку кодовая база становится большой, я нашел, что это стало менее последовательным об определении с помощью документации, какие методы имеют ограничения поточной обработки: обычно, методы, которые должны быть выполнены на EDT Swing. Точно так же было бы полезно знать и обеспечить статическую осведомленность, в которую (нашего пользовательского) слушатели уведомляются относительно EDT спецификацией.

Таким образом, это прибыло ко мне, что это должно быть чем-то, что могло быть легко осуществлено с помощью аннотаций. О чудо, там существует по крайней мере один инструмент статического анализа, CheckThread, который использует аннотации для выполнения этого. Это, кажется, позволяет Вам объявлять, что метод ограничен определенным потоком (обычно EDT) и отметит методы, которые пытаются назвать тот метод, также не объявляя себя, как заключено тем потоком.

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

  • Есть ли какие-либо истории успеха для людей использование CheckThread или подобные библиотеки для осуществления ограничений поточной обработки? Какие-либо истории отказа? Почему это следовало/приводило к сбою?
  • Действительно ли это хорошо в теории? Есть ли теоретические оборотные стороны?
  • Действительно ли это хорошо на практике? Действительно ли это стоит того? Какое значение это поставило?
  • Если это работает на практике, что хорошие инструменты должны поддерживать это? Я только что нашел CheckThread, но признаю, что я не совсем уверен, что я ищу для нахождения других инструментов, которые делают то же самое.

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

27
задан 3 revs, 3 users 97% 13 January 2016 в 17:55
поделиться

3 ответа

Этот ответ больше сфокусирован на теоретическом аспекте вашего вопроса.

По сути, вы утверждаете: «Этот метод работает только в определенных потоках». Это утверждение на самом деле не отличается от любого другого утверждения, которое вы могли бы сделать («Метод принимает только целые числа меньше 17 для параметра X»). Вопросы заключаются в следующем:

  • Откуда берутся такие утверждения?
  • Могут ли статические анализаторы их проверять?
  • Где взять такой статический анализатор?

В основном такие утверждения должны исходить от разработчиков программного обеспечения, так как они есть единственные люди, которые знают намерения.Традиционный термин для этого - «Дизайн по контракту», хотя большинство схем DBC находятся только над текущим состоянием программы (макрос C assert ), и они действительно должны перекрывать прошлое и будущее состояния программ («временные утверждения»), например. , g., «Эта процедура выделит блок памяти, и в конечном итоге какой-то фрагмент кода освободит его». Можно создать инструменты, которые пытаются определить с помощью геризма, что представляют собой утверждения (например, индукционная работа с утверждениями Энглера; другие уже проделали работу в этой области). Это полезно, но ложные срабатывания - проблема. С практической точки зрения просьба к дизайнерам закодировать такие утверждения не кажется особенно обременительной и действительно является хорошей долгосрочной документацией. Кодируете ли вы такие утверждения с помощью специальной языковой конструкции «Контракт» или с помощью оператора if («if Debug && Not ( assertion ) Then Fail ();») или скрываете их в аннотации - это просто вопрос удобства. Приятно, когда язык позволяет напрямую кодировать такие утверждения.

Статическая проверка таких утверждений затруднительна. Если вы придерживаетесь только текущего состояния, статический анализатор в значительной степени должен выполнять полный анализ потока данных всего вашего приложения, потому что информация, необходимая для удовлетворения утверждения, вероятно, поступает из данных, созданных другой частью приложения. (В вашем случае сигнал «внутри EDT» должен исходить от анализа всего графа вызовов приложения, чтобы увидеть, есть ли какой-либо путь вызова, ведущий к методу из потока, который НЕ является потоком EDT).Если вы используете временные свойства, статическая проверка в значительной степени требует дополнительной логики проверки в пространстве состояний; в настоящее время это все еще инструменты исследования. Даже со всем этим оборудованием статические анализаторы обычно должны быть «консервативными» в своих анализах; если они не могут продемонстрировать, что что-то ложно, они в значительной степени должны предположить, что это правда, из-за проблемы с остановкой.

Где взять такие анализаторы? Учитывая всю необходимую технику, их сложно построить, поэтому вы должны ожидать, что они будут редкостью. Если кто-то построил такой - отлично. Если нет ... как правило, вы не хотите делать это самостоятельно с нуля. Лучшая долгосрочная надежда - это иметь в наличии универсальное оборудование для анализа программ, на котором можно будет построить такие анализаторы, чтобы амортизировать стоимость создания всей инфраструктуры. (Я создаю основы инструментов для анализа программ; см. Наш DMS Software Reengineering Toolkit ).

Один из способов «упростить» создание таких статических анализаторов - ограничить обрабатываемые ими случаи узкой областью, например CheckThread. Я ожидал, что CheckThread будет делать именно то, что делает сейчас, и вряд ли станет намного сильнее.

Причина того, что макросы «assert» и другие подобные динамические проверки «текущего состояния» популярны, заключается в том, что они фактически могут быть реализованы с помощью простого теста времени выполнения. Это довольно практично. Проблема здесь в том, что вы никогда не сможете пройти путь, ведущий к неудачным условиям. Таким образом, для динамического анализа отсутствие обнаруженной неисправности на самом деле не является свидетельством правильности. Все еще чувствует себя хорошо.

Итог: у статических и динамических анализаторов есть свои сильные стороны.

8
ответ дан 28 November 2019 в 05:54
поделиться

Мы не пробовали никаких инструментов статического анализа, но мы использовали AspectJ, чтобы написать простой аспект, который обнаруживает во время выполнения, когда любой код в java.awt или javax.swing вызывается вне EDT. Он обнаружил в нашем коде несколько мест, в которых отсутствует SwingUtilities.invokeLater () . Мы работаем с включенным аспектом на протяжении всего цикла контроля качества, а затем отключаем его незадолго до выпуска.

3
ответ дан 28 November 2019 в 05:54
поделиться

Согласно запросу, это не относится конкретно к Java или EDT, но я видел хорошие результаты с помощью программ проверки статического анализа параллелизма Coverity для C / C ++. У них действительно был более высокий уровень ложных срабатываний, чем у менее сложных программ проверки, но владельцы кода, похоже, были готовы смириться с этим, учитывая, насколько сложно найти ошибки потоковой передачи с помощью тестирования. Боюсь, детали являются конфиденциальными, но публичные документы Доусона Энглера (например, «Ошибки как отклоняющееся поведение») очень хороши в отношении общего подхода «Следующие« N »экземпляров вашего кода делают« X »перед тем, как« делать ». Y »,; в этом случае нет ».

2
ответ дан 28 November 2019 в 05:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: