Я использую оба. Думаю, они дополняют друг друга.
Как вы сказали, PMD работает с исходным кодом и поэтому обнаруживает такие проблемы, как: нарушение соглашений об именах, отсутствие фигурных скобок, неправильная проверка нуля, длинный список параметров, ненужный конструктор, отсутствие разрыва в переключателе и т. Д. PMD также сообщает вам о Cyclomatic сложность вашего кода, который я считаю очень полезным (FindBugs не сообщает вам о цикломатической сложности).
FindBugs работает с байт-кодом. Вот некоторые проблемы, которые FindBugs обнаруживает, чего не делает PMD: метод equals () не работает для подтипов, метод clone может возвращать null, эталонное сравнение логических значений, невозможное приведение, 32-битное int, сдвинутое на величину, не находящуюся в диапазоне 0-31, коллекция, которая содержит себя, метод equals всегда возвращает true, бесконечный цикл и т. д.
Обычно каждый из них находит свой набор проблем. Используйте оба. Эти инструменты научили меня многому в том, как писать хороший Java-код.