Pull to refresh

Comments 58

Спасибо. Интересно посмотреть на другой язык. Прочитал как-бы свою статью со стороны. Интересное ощущение. :) Глядишь, и заинтересуются российские программисты методологией статического анализа. У нас явно в этом какой-то пробел. Хотя, пожалуй, это следствие, что огромная часть решаемых задач — аутсорс.
P.S. Главное, не признавайтесь в заговоре. Тссс! :)
Вы забыли спросить «А сообщили ли об ошибках разработчику?»
Как-то так:
sourceforge.net/p/cdk/bugs/1314/
Всё описывать не стал, просто прорекламировал FindBugs в конце. Зато не поленился вычислить подходящий random seed (0x260E92790EB7L)!
Было бы интересно посмотреть на результат статического анализа самого статического анализатора:)
Думаю, это довольно скучное занятие: авторы анализатора сами анализатором проверяют свой код постоянно и всё интересное исправляют сразу даже до коммита в репозиторий.
Интересно, а может быть такая ситуация при которой баг в статическом анализаторе не будет показывать, что это баг самого статического анализатора?
Возможна ли ситуация, когда в программе есть ошибка?
Очевидно же, что это очень и очень редкий случай:)
Может уже спрашивали в других статьях, но есть ли подобный анализатор для C#?
Resharper же. Очень много всего подсказывает прямо в коде и предлагает прямо на месте исправить с помощью Quick Fixes.
Не ну мне кажется что Resharper «не так крут» как специализированная программа. До Resharper-а всё руки не доходят купить его и покатать на своих прогах.
«не так крут» как специализированная программа

Интересно, что есть тогда решарпер?
Я исхожу из той предпосылки что чайник-роутер будет не таким хорошим чайником и не таким хорошим роутером как собственно чайник и роутер ;)

А вообще, как я сказал, всё еще руки не дошли поиграться с самим решарпером, может он и правда крут :)
Решарпер хорош тем, что показывает подозрительные места прямо во время разработки. Это удобно тем, что ошибка привязана к контексту: легче исправить баг в том конкретном участке, с которым вы работаете сейчас, чем в произвольном месте всего проекта.
Кроме того, можете посоветовать им на Issue Tracker'е свой quickfix или inspection, если есть идеи. Правда, мой до сих пор не запилили :(
У них command line tools вышли с 8 R#, там есть анализатор. Да, и оно вроде как бесплатное.
Так вроде все по объектному файлу косяки ищут.
Конкретно в этом случае надо использовать replace, а не replaceAll. Причём лучше тот, который от (char, char), и передать File.separatorChar. Это будет в разы быстрее.
По поводу номера 3.
Разве Java не оптимизирует проверку условий? Это же логическое «И». Получается, что если первое выражение вернет false, то вычислять вторую часть нет смысла.
Используя & мы сами говорим — «Обязательно проверь и остальное!»
Это называется Short-circuit evaluation или «сокращенные логические операции»
В Java при использовании & и/или | второй опреанд вычисляется всегда, даже если результат известен исходя из значения первого операнда. При Short-circuit evaluation(&& ||) лишних вычислений не производится.
SonarQube + Jenkins — отличная связка для автоматического статического анализа кода
Помимо анализа на ошибки, есть еще куча настраиваемых метрик, по которым даже прогресс можно отслеживать
А ещё Sonar использует не только FindBugs, но и Checkstyle и PMD. А если ещё прикрутить это в виде плагина к IDE для проверки в реальном времени — вообще получается сказка.
А напомните мне пожалуйста, в таком случае —

line.trim();

— байт код вообще будет генерироваться, или компилятор просто выкинет данный вызов?
Байт код сгенерируется. Но потом — во время выполнения, на этапе оптимизации, вполне может выкинуть.
Останется. Проверил на 1.7_21
почему же ему не генерироваться? возвращаемое значение можно игнорировать, но это не значит, что метод ничего не делает и его можно спокойно вырезать, даже если он просто занимает процессорное время.
почему не значит? если метод без сайд эффектов и его возвращаемое значение не используется, этот метод оптимизирующему компилятору можно и нужно выкинуть. что собственно в ряде языков и делается.

trim логически выглядит как метод который должен быть методом без сайд эффектов :)

собственно вопрос в яве новая строка появится в string pool в какой момент, уже внутри вызов trim или только в момент возвращение значения, если в момент то логически trim это метод без сайд эффектов, просто компилятор явы не может это выяснить, хотя хотелось бы
Компилятор Java в байт-код практически ничего не оптимизирует. Зато ваши .class-файлы довольно независимы. К примеру, в рантайме вы можете подсунуть другой rt.jar и подменить реализацию .trim() на такую, которая уже даст side-effect. Практически все оптимизации выполняются на уровне JIT-компиляции.
Компилятор Java в байт-код практически ничего не оптимизирует
Есть определённые исключения (которые, кстати, очень мешают). Например (классический пример), при компиляции подставляются значения публичных констант, описанных в других классах. В итоге может получиться такая ситуация, что ты константу переопределил, класс, в котором она описана, перекомпилировал (а остальные не стал), а в месте использования реальное значение осталось старое.
Читайте «изменил её значение в исходнике».
Скажем, есть у нас класс A:
public class A {
    public static final String SOME_CONSTANT = "1";
}

И есть класс B:
import A;
public class B {
    public static void main(String[] args) {
        System.out.println("A.SOME_CONSTANT = " + A.SOME_CONSTANT);
    }
}

Компилируем, запускаем, получаем ожидаемый результат:
A.SOME_CONSTANT = 1

Теперь меняем класс A следующим образом:
public class A {
    public static final String SOME_CONSTANT = "2";
}

Компилируем _только_ его (не перекомпилируя класс B), заменяем файл A.class, запускаем — и получаем не то, чего ожидали:
A.SOME_CONSTANT = 1
вместо
A.SOME_CONSTANT = 2
С 1.) есть другая серъёзная проблема: если была цель получить равномерно распределённое число в диапазоне [low, hi], то она не достигнута.

Например, если low==0 и hi==(2/3 от максимального int), то в полученном распределении числа в диапазоне [0, max_int/3] встречаются в два раза чаще, чем в диапазоне [max_int/3, 2*max_int/3]
довольно странный код вообще, учитывая, что есть nextInt(int n).
Да, я хотел про это написать, но решил не отвлекаться от основной темы статьи и предоставить эту возможность комментаторам :-)
> 6. Сравнение объектов разных типов
Может в atom.equals определено сравнение со строкой? Правда это было бы нарушением контракта Object.equals
Вы можете скачать исходники и убедиться, что это не так :-)
Большинство ошибок на уровне детского сада.
Вы не поверите: большинство ошибок в программировании вообще — на уровне детского сада. Даже у самых крутых разработчиков (разумеется, кроме Джеффа Дина).
Какую версию FindBug использовали? По моему опыту версия 2 стала находить ошибок гораздо больше
Такое ощущение, что разработчики не только не пользуются статическим анализом, но и вообще пишут код в Блокноте. Вроде, все современные IDE проверяют, не пытается ли разработчик подсунуть в equals значения не приводимых типов.
Запустил на пробном проекте (который с нуля сам пишу), только пару спорных вещей нашел. Все же в IDEA тоже встроен анализатор.
На рабочем проекте нашло около 2000, быстро проглядел группы проблем, есть парочка серьезных. Буду встраивать в наш Jenkins.

Советую сразу SonarQube. В нём есть не только FindBugs, но ещё и Checkstyle с PMD, плюс свои проверки. С Jenkins-ом SonarQube вполне дружит — можно либо установить плагин для Jenkins-а, либо воспользоваться плагином для maven-а и при сборке добавить в параметры мавена sonar:sonar (мы сделали именно так). Ну и опять же — история проекта с красивыми табличками и графиками, уведомления по почте, назначение замечаний на конкретных людей (можно заводить соответствующие задачи в issue tracker-ах) и т.д.
Хм, так это отдельное приложение? Т.е. нельзя взять и просто добавить плагин в Jenkins, нужно его ставить отдельно?
Через maven не получится, проект древний, на ant :(
SonarQube? Да, это отдельное веб-приложение. FindBugs сам по себе, конечно, можно прикрутить отдельным плагином к Jenkins-у (и даже это уже будет хорошо), но на мой взгляд SonarQube гораздо, гораздо удобнее. А ставится он очень просто.
FindBugs крайне полезен. К тому же, помимо eclipse плагина, у него есть maven плагин и возможность запускаться во время билда CI сервером. В общем-то, как и у Checkstyle и PMD (о которых уже упоминали в комментах).
Checkstyle, кстати, стоит использовать одновременно с FindBugs. Если FB анализирует байт-код, то CS анализирует исходники и находит различные проблемы с стандартами именования, форматирования кода — FindBugs'у неведомые.

Помимо этой троицы, есть CodePro Analytix. Который умеет намного больше предыдущих. Но, к сожалению, после того как он перешел к Google, его перестали поддерживать. Оффициально, существует только версия плагина для eclipse 3.6 (что не мешает ему почти полностью работать и под 3.7 и под 4.2.2). И у него, к сожалению, нет maven плагина (или же я плохо искал). Но CodePro помимо статического анализа (с большим количеством правил чем у FB и CS), умеет анализировать покрытие кода тестами, различные метрики, анализировать зависимости и находить похожий код (т.е. потенциально дублирование кода). Еще вроде умеет генерить юнит тесты, но пользоваться этим мне никогда не доводилось. А так, очень удобный комбайн.
Большое спасибо за статью! Прочитал про FindBugs и решил его попробовать, но не получилось, помогите пожалуйста запустить. Eclipse Juno Service 2. Делаю Help — Install new Siftware — work with «findbugs.cs.umd.edu/eclipse-daily», Next, Yes, Next, Finish. Перезапускаю Eclipse, вижу перспективу FindBugs, слева BugExplorer, но он пустой. Как запустить проверку кода проекта?
Нажмите правой кнопкой на своём проекте (в Project explorer или Package explorer), там Find Bugs -> Find Bugs.
Получилось! Большое спасибо!
Sign up to leave a comment.

Articles