Поиск неиспользуемого кода в Java с помощью AspectJ

У меня есть идея найти неиспользуемые («мертвые») методы в большом Java-проекте, но мне нужна помощь в реализации.

  1. Используйте AspectJ, чтобы добавить аспект «до» ко ВСЕМ методам в пакетах проектов. Аспект просто запишет (?), Что метод был выполнен.
  2. Я составляю список всех классов / методов в пакетах проекта (возможно, используя локатор / отражение сервисов).
  3. Рекомендуемый код подвергается полному регрессионному тесту. В идеале я бы тоже хотел на время запустить это в производство (если удастся найти подходящее решение).
  4. Списки выполненных методов (шаг 1) и доступных методов (шаг 2) сравниваются, что дает исчерпывающий список всех методов, которые никогда не вызывались (т. Е. Мертвый код).

Поскольку шаги 2 и 4 можно выполнять в автономном режиме, мне действительно нужна помощь только по шагу 1.

В частности, как я могу записать, когда метод выполняется? Я полагаю, что довольно скоро столкнусь с OutOfMemoryErrors, если попытаюсь использовать какое-либо хранилище в памяти. Точно так же, если я храню данные в базе данных / в файловой системе, объем вызовов может вызвать серьезные проблемы с производительностью. Кто-нибудь когда-нибудь делал что-нибудь подобное? Любые советы / предложения приветствуются.


person hoipolloi    schedule 22.07.2011    source источник


Ответы (2)


Попробуйте ознакомиться с популярными библиотеками покрытия тестов, такими как Cobertura или EMMA. Они делают именно то, о чем вы говорите, а также некоторые другие, но не с AspectJ. По крайней мере, у Cobertura, похоже, нет проблем с сохранением информации о вызовах до строки в памяти.

person Ryan Stewart    schedule 22.07.2011
comment
Я рассматривал Cobertura, но меня беспокоит снижение производительности инструментального кода, который записывает построчный анализ. Как видите, я даже не уверен, что анализ на уровне методов осуществим. Однако, если у кого-то есть доказательства обратного, я бы хотел их услышать. - person hoipolloi; 22.07.2011
comment
@hoipolloi: Я просто хотел посмотреть на него и посмотреть, как он хранит собранные данные в памяти во время сбора. Учитывая объем собираемых данных, он может дать вам представление о том, где вам нужно быть. - person Ryan Stewart; 22.07.2011
comment
@hoipolloi: Кроме того, вы говорите о проведении этого анализа в долгосрочной перспективе в производственной среде или просто в тестовой среде, например, в инструменте покрытия тестами? - person Ryan Stewart; 22.07.2011
comment
Ах, хороший звонок - я посмотрю. Я думал о долгосрочной перспективе (несколько месяцев), чтобы мы могли быть уверены, что используются все элементы приложения. - person hoipolloi; 22.07.2011
comment
@hoipolloi: Если вы собираетесь работать надолго, вы можете использовать то, что вы найдете в cobertura / emma, для сбора результатов в памяти, а затем периодически (ежечасно, ежедневно, что угодно) сбрасывать собранные результаты в базу данных и удалять их из объем памяти. Вы должны быть осторожны с проблемами параллелизма, поскольку вы удаляете материал из памяти, поскольку потенциально добавляются другие элементы. Я не знаю ни одной библиотеки или фреймворка, которые бы сильно помогли в этом, кроме использования планировщика для запуска сбросов. - person Ryan Stewart; 22.07.2011

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

Я думаю, вам лучше просто использовать инструмент для анализа двоичных файлов .class с помощью BECL или ASM, начиная с методов, которые вы знаете < / em> получить звонок и построить график звонков. Это похоже на то, как JVM выполняет сборку мусора.

Но на самом деле вы должны спросить себя, что это такое. Это производительность? Потому что удара быть не должно. Если вы хотите уменьшить размер файлов .class, вам лучше использовать что-нибудь вроде ProGuard. Это позаботится об этом и других проблемах, и это уже сделано.

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

person Sled    schedule 22.07.2011
comment
Статический анализ кода завершится ошибкой, поскольку большая часть кода выполняется во время выполнения посредством отражения. Значительные ручные усилия также невозможны из-за размера базы кода (›5 млн строк). Кроме того, многие бизнес-знания были потеряны с течением времени, поэтому есть области кода, которые мы не «знаем». Наконец, это процесс «протоколирования» выполнения, который меня интересует. Мне нужен способ сделать это, не ставя приложение на колени (с точки зрения производительности). - person hoipolloi; 22.07.2011
comment
@hoipolloi Что ж, если вы знаете, откуда исходит отражение и куда оно обычно направляется, вы можете добавить эти точки в свой список базовых точек. Если есть много отражений, которые идут повсюду, вероятно, что-то действительно не так ... Но я бы не стал беспокоиться о производительности, поскольку вы должны быть в состоянии найти пути к живому коду с развертыванием в тестовой среде и выполнением основных функций приложение. - person Sled; 22.07.2011
comment
Согласны, что в нормальных условиях полный регрессионный тест должен охватывать все пункты. Однако это устаревшее приложение (я подозреваю, что с большим количеством устаревшего кода), и я совершенно не верю в наши текущие возможности регрессионного тестирования. Боюсь, обычная история; недостаточно финансируется и недостаточно ресурсов. Хорошим твердым шагом в возвращении кода под контроль было бы удаление огромного количества мертвого кода, чтобы мы не тратили время на написание тестов для кода, который больше не используется. - person hoipolloi; 23.07.2011