Similar to Checkstyle, PMD is a static code analysis tool that is targeted more toward improving code quality than explicitly scanning for security problems. PMD does promote certain aspects that have indirect effects on product security, which is why I usually recommend using it regularly during development.
Many security defects are introduced because code is overly complex or because developers do not deeply care about or understand the code that they are writing. Copy and pasting (e.g. from blogs, Stack Overflow, …) contributes to this effect. I have had the experience that with increasing code quality, the number of security defects decreases. This is not because a tool like PMD makes developers smarter, I think this is because a tool like PMD can help force developers to think about the code they are writing, and to spot obvious blunders that may later on lead to security issues.
PMD is applying “rules” on the code, with each “rule” describing desired (or: undesired) code structures. PMD comes with a huge set of rules, and choosing the best rules for a project is not always easy: some of the rules are controversial in the first place (they are conveniently placed in the “controversial” ruleset package), others may be contradicting. Users can create additional (custom) rules, and add them to the rule set as needed.
Security reviewers are generally very appreciate of code that is easy to follow. The “basic”, “code size”, “coupling”, and “design” rule sets are particularly helpful for creating easily readable code. This also has the nice benefit that such code is easy to maintain. No more “what did I want to achieve with this somewhat overly optimized block of code that has more double negotiations in it than the CEO’s last speech on salary increases” situations after coming back from vacation.
PMD is very good at discovering dead code, overly complicated expressions, and code that has a high formal complexity (e.g. NCSS, cyclomatic complexity, NPath complexity, field and parameter counts, etc) – all of which can eventually lead to security problems due to complexity-induced incorrect code usage. PMD helps developers to truly remove of this hand-optimized code, and leave that kind of work to the compiler. At the same time, PMD can also spot inefficient code, and help the developer to manually optimize where a human brain is actually smarter than the compiler.
In combination with Checkstyle, PMD can catch a lot of bad coding habits.
The available rules change frequently with new PMD releases. A current list (for the 5.1.1 release) is available here.
Edit: See the “build-tools” project in https://github.com/mbeiter/util for a starting point for creating a PMD ruleset definition. The rules configured in this project are the ones that I personally find generally useful. Keep in mind that this really is only a starting point, as each project may have individual needs for an optimal rule set depending on the data it is processing, how it is operated, etc pp.