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