Как найти неиспользуемый / мертвый код в Java-проектах [закрыто]

306

Какие инструменты вы используете, чтобы найти неиспользуемый / мертвый код в больших проектах Java? Наш продукт разрабатывался в течение нескольких лет, и очень трудно вручную обнаружить код, который больше не используется. Однако мы стараемся удалить как можно больше неиспользуемого кода.

Предложения для общих стратегий / методов (кроме конкретных инструментов) также приветствуются.

Изменить: Обратите внимание, что мы уже используем инструменты покрытия кода (Clover, IntelliJ), но они мало помогают. У мертвого кода все еще есть юнит-тесты, и он отображается как покрытый. Я предполагаю, что идеальный инструмент идентифицирует кластеры кода, у которых очень мало другого кода в зависимости от него, что позволяет проводить проверку документов вручную.

knatten
источник
16
Храните юнит-тесты в отдельном дереве исходных текстов (в любом случае, вы должны это сделать) и запускайте инструменты покрытия только на живом дереве.
agnul
5
Я бы начал с проверки IDEA "Неиспользованная декларация" и снял флажок Включить источники тестов . Можете ли вы уточнить, что вы имеете в виду, когда говорите, что IDEA «мало помогает»?
Дэвид Моулз
1
Способы поиска мертвого кода: 1) не связаны ничем снаружи. 2) не использовался извне, хотя и был связан во время выполнения. 3) Связано и вызвано, но никогда не используется как мертвая переменная. 4) логически недостижимое состояние. Так что связывание, доступ с течением времени, логика, использование после доступа.
Мухаммед Умер
Используйте IntelliJ Idea и мой ответ отсюда: stackoverflow.com/questions/22522013/… :)
BlondCode
Дополнение к ответу Дэвида Моуля: см. Этот ответ stackoverflow.com/a/6587932/1579667
Benj

Ответы:

40

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

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

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

akuhn
источник
5
Мне нравится этот ответ, но есть ли у кого-нибудь идея, как сделать это в Java без явного добавления регистрации в каждом классе? Может быть, какая-то магия «Прокси»?
Программист вне закона
14
@Outlaw AOP кажется идеальным вариантом для этого.
Паскаль Thivent
6
Если вы понимаете структуру загрузки классов приложения, вы можете использовать AOP на загрузчике классов для отслеживания событий загрузки классов. Это было бы менее инвазивным в производственной системе, чем совет перед всеми конструкторами.
ShabbyDoo
5
Этот ответ довольно хорош для динамического языка, но ужасен для статического языка, который мог бы сделать НАМНОГО лучше. Со статически типизированным языком (кроме рефлексии) вы можете точно знать, какие методы используются, а какие нет. Это одно из самых больших преимуществ статически типизированного языка, и вы должны использовать его, а не ошибочный метод, как описано здесь. ,
Билл К
4
@BillK происходит больше размышлений, чем вы думаете. Например, Spring делает немного магии под одеялом, в том числе отражения. Ваш инструмент анализа должен имитировать это.
Торбьерн Равн Андерсен
220

Плагин Eclipse, который работает достаточно хорошо, это Unused Code Detector .

Он обрабатывает весь проект или конкретный файл и отображает различные методы неиспользуемого / мертвого кода, а также предлагает изменения видимости (то есть открытый метод, который может быть защищен или закрыт).

Mikezx6r
источник
Выглядит хорошо, но я не смог заставить его работать - действие «Обнаружить код un ...» отключено, и я не нашел способа его включить.
Ондра Жижка
1
Действительно, найдите неиспользуемые методы, НО также обнаружите, что мои EJB-компоненты не используются (пока они есть), потому что я использую дизайн шаблона бизнес-делегата
Eildosa
Это все еще работает на kepler? релизы говорят о затмении 3.8: ucdetector.org/releases.html
Mr_and_Mrs_D
Кажется, на Кеплер в идеальном рабочем состоянии.
Эрик Каплун
4
Хотите добавить ссылку на рынок marketplace.eclipse.org/content/unneeded-code-detector ? Это облегчает установку и отвечает на вопрос, поддерживается ли он в более новых версиях Eclipse.
Томас Уэллер
64

CodePro был недавно выпущен Google вместе с проектом Eclipse. Это бесплатно и очень эффективно. Плагин имеет функцию « Найти мертвый код » с одной / несколькими точками входа. Работает довольно хорошо.

Берлин Браун
источник
1
Больше не буду работать с затмением Кеплера. После успешной установки через сайт обновлений каждый раз происходит аварийное завершение.
txulu
К сожалению, похоже, что этот инструмент не осознает существование Spring, поэтому он пометит все мои @Components как неиспользуемые, ошибочно
Клинт Иствуд
Стать очень старым Больше не работает Last updated this plugin March 27, 2012 developers.google.com/java-dev-tools/download-codepro
mumair
2
Все ссылки устарели.
Зигимантус
3
К сожалению, похоже, что Google сбросил код в проекте Eclipse и забыл все об этом.
Торбьерн Равн Андерсен
30

Я удивлен, что ProGuard здесь не упоминается. Это один из самых зрелых продуктов.

ProGuard - это бесплатный инструмент для сжатия файлов класса Java, оптимизатор, обфускатор и предварительный анализатор. Он обнаруживает и удаляет неиспользуемые классы, поля, методы и атрибуты. Он оптимизирует байт-код и удаляет неиспользуемые инструкции. Переименовывает остальные классы, поля и методы, используя короткие бессмысленные имена. Наконец, он предварительно проверяет обработанный код для Java 6 или для Java Micro Edition.

Некоторые виды использования ProGuard:

  • Создание более компактного кода, для небольших архивов кода, более быстрая передача по сети, более быстрая загрузка и меньшие объемы памяти.
  • Создание программ и библиотек сложнее для обратного проектирования.
  • Перечисление мертвого кода, поэтому его можно удалить из исходного кода.
  • Перенацеливание и предварительная проверка существующих файлов классов для Java 6 или более поздней версии, чтобы в полной мере воспользоваться их более быстрой загрузкой классов.

Вот пример для списка мертвых кодов: https://www.guardsquare.com/en/products/proguard/manual/examples#deadcode

Дэвид д С е Фрейтас
источник
8
Предоставление образца использования сделало бы лучший ответ.
Rds
1
Читая документацию, я вижу, что он сокращает неиспользуемый код, но я не могу найти нигде, где он перечисляет его - согласился, пример или ссылка на соответствующий раздел документации, были бы весьма полезны!
orbfish
26

Одна вещь, которую я знал в Eclipse для одного класса, - это изменить все его методы на приватные, а затем посмотреть, какие жалобы я получаю. Для используемых методов это вызовет ошибки, и я верну их к самому низкому уровню доступа. Для неиспользуемых методов это вызовет предупреждения о неиспользуемых методах, которые затем можно будет удалить. И в качестве бонуса вы часто находите некоторые публичные методы, которые можно и нужно сделать приватными.

Но это очень ручной.

skiphoppy
источник
4
Может быть, не идеальный ответ, но это действительно умный.
Эрик Реппен
8
Это умно ... до тех пор, пока вам не позвонят из неиспользуемого кода из другого класса.
Danosaure
Повторение этого метода может привести к удалению огромного количества кода, так как один используемый метод создает другие после его удаления.
миль,
15

Используйте инструмент покрытия тестов, чтобы оборудовать свою кодовую базу, затем запустите само приложение, а не тесты.

Эмма и Эклемма дадут вам хорошие отчеты о том, какой процент классов выполняется для любого данного прогона кода.

jamesh
источник
1
+1, поскольку это хорошая отправная точка, но имейте в виду, что, например, неиспользуемые (пока не объявленные) переменные также станут зелеными.
DerMike
13

Мы начали использовать Поиск ошибок, чтобы помочь идентифицировать некоторые из фанков в среде, богатой целями нашей кодовой базы для рефакторинга. Я бы также рассмотрел Структуру 101, чтобы идентифицировать места в архитектуре вашей кодовой базы, которые слишком сложны, чтобы вы знали, где настоящие болота.

Алан
источник
4
FindBugs не может обнаружить мертвый и неиспользуемый код, только неиспользуемые поля. Смотрите этот ответ .
Стефан Мюке
12

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

Это может проявиться в коде Java разными способами:

  • Загрузка классов на основе пользовательского ввода, файлов конфигурации, записей базы данных и т. Д .;
  • Загрузка внешнего кода;
  • Передача деревьев объектов сторонним библиотекам;
  • и т.п.

При этом я использую IDEA IntelliJ в качестве своей предпочтительной среды IDE, и она имеет обширные инструменты анализа для поиска зависимостей между модулями, неиспользуемыми методами, неиспользуемыми членами, неиспользуемыми классами и т. Д. Он также достаточно интеллектуален, как частный метод, который не вызывается. помечены как неиспользованные, но публичный метод требует более тщательного анализа.

Клетус
источник
1
Спасибо за ваш вклад. Мы используем IntelliJ и получаем некоторую помощь там. Что касается проблемы остановки и неразрешимости, я знаком с теорией, но нам не обязательно нужно детерминистическое решение.
вязать
12
Вступительное предложение слишком сильно. Как и в случае с проблемой остановки (также часто неправильно цитируемой / оскорбленной), полных общих решений не существует, но существует множество особых случаев, которые можно обнаружить.
joel.neely
9
Хотя не существует общего решения для языков с eval и / или отражением, во многих случаях код недостижим.
pjc50
1
Без размышлений и с полным исходным кодом любой статически типизированный язык должен довольно легко детерминистически найти весь неиспользуемый код.
Билл К
Вы не можете найти, что доказуемо недоступно с помощью отражения или внешних вызывающих абонентов, но вы можете найти код, который доказуемо недоступен статически с заданной точки входа или набора точек входа
nafg
8

В Eclipse зайдите в Windows> «Установки»> «Java»> «Компилятор»> «Ошибки / предупреждения»
и измените их все на ошибки. Исправьте все ошибки. Это самый простой способ. Прелесть в том, что это позволит вам очистить код во время написания.

Скриншот Eclipse Code:

введите описание изображения здесь

smileprem
источник
5

IntelliJ имеет инструменты анализа кода для обнаружения кода, который не используется. Вы должны попытаться сделать как можно больше закрытых полей / методов / классов, и это покажет больше неиспользуемых методов / полей / классов

Я также попытался бы найти дублирующийся код для уменьшения объема кода.

Мое последнее предложение - попытаться найти открытый исходный код, который в случае его использования сделает ваш код проще.

Питер Лори
источник
Какие-нибудь примеры того, что эти инструменты?
orbfish
@orbfish Вы можете запустить Analyse=> Run inspection by name=>unused
Питер Лори
5

Перспектива среза Structure101 предоставит список (и граф зависимостей) любых «сирот» или « групп сирот » классов или пакетов, которые не имеют зависимостей от «основного» кластера или от него.

Крис Чеджи - Structure101
источник
Работает ли это для переменных экземпляра / методов в классе?
Joeblackdev
Как узнать, должно ли это работать, например, с Eclipse 4.3?
Эрик Каплун
3

DCD не является плагином для какой-то IDE, но может быть запущен из ant или standalone. Он выглядит как статический инструмент и может делать то, что PMD и FindBugs не могут . Я попробую.

PS Как уже упоминалось в комментарии ниже, проект сейчас живет в GitHub .

Хайнер
источник
Это должно идти вниз , как комментарий не ответ
графа
Пожалуйста, обновите свой ответ, чтобы убрать ваше заявление о том, что DCD "выглядит мертвым сейчас" Версия 2.1 была выпущена 12 дней назад . Также ссылка в вашем ответе не работает.
скомиса
2

Существуют инструменты, которые профилируют код и предоставляют данные покрытия кода. Это позволяет увидеть (по мере выполнения кода), сколько из этого вызывается. Вы можете получить любой из этих инструментов, чтобы узнать, сколько у вас есть бесхозный код.

Vaibhav
источник
2
  • FindBugs отлично подходит для такого рода вещей.
  • PMD (Project Mess Detector) - еще один инструмент, который можно использовать.

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

graveca
источник
1

Инструменты покрытия пользователей, такие как EMMA. Но это не статический инструмент (т. Е. Он требует запуска приложения через регрессионное тестирование и через все возможные случаи ошибок, что, в общем-то, невозможно :))

Тем не менее, EMMA очень полезна.

Владимир Дюжев
источник
1

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

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

Я полагаю, что наилучшим способом действительно идентифицировать мертвый код было бы снабдить ваш код инструментом покрытия в действующей среде и проанализировать покрытие кода в течение длительного периода времени.

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

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

Vihung
источник
1

Есть Java-проект - Dead Code Detector (DCD). Для исходного кода это, кажется, не работает хорошо, но для файла .jar - это действительно хорошо. Плюс вы можете фильтровать по классу и по методу.

Лукаш Червинский
источник
0

Eclipse может показать / выделить код, который не может быть достигнут. JUnit может показать вам покрытие кода, но вам потребуются некоторые тесты и вы должны решить, отсутствует ли соответствующий тест или код действительно не используется.

Матиас Винкельманн
источник
3
Eclipse сообщит вам только, если область действия метода является локальной (то есть частной); и даже тогда вы не можете быть уверены на 100% ... с отражением, частный метод может вызываться извне
p3t0r
0

Я нашел инструмент покрытия Clover, который инструментирует код и выделяет код, который используется и который не используется. В отличие от Google CodePro Analytics, она также работает для веб-приложений (по моему опыту, и я могу ошибаться насчет Google CodePro).

Единственный недостаток, который я заметил, это то, что он не учитывает интерфейсы Java.

Кашиф Назар
источник
Afaict, это несвободный инструмент CI на стороне сервера.
Эрик Каплун
0

Я использую Doxygen для разработки карты вызовов методов, чтобы найти методы, которые никогда не вызываются. На графике вы найдете острова кластеров методов без абонентов. Это не работает для библиотек, так как вам всегда нужно начинать с некоторой главной точки входа.

jbruni
источник