Skip to content

Releases: pmd/pmd

PMD 7.26.0-SNAPSHOT (12-June-2026)

29 May 07:50
7753d9e

Choose a tag to compare

Pre-release

29-June-2026 - 7.26.0-SNAPSHOT

The PMD team is pleased to announce PMD 7.26.0-SNAPSHOT.

This is a minor release.

Table Of Contents

🚀️ New and noteworthy

🌟️ New and Changed Rules

New Rules

  • The new Java rule WrongTestAnnotation detects when test annotations from the wrong
    testing framework (JUnit 4, JUnit Jupiter, or TestNG) are used in your code, preventing tests from being silently
    skipped due to framework mismatches. This helps avoid the silent failure where tests compile but don't execute
    because the test runner doesn't recognize the annotation.
  • The new Kotlin rule LocalVariableShadowsParameter detects local variable
    declarations that use the same name as a parameter of the enclosing function. This shadows the parameter
    and may lead to confusion about which value is used.

🐛️ Fixed Issues

  • apex-security
    • #2955: [apex] ApexSOQLInjection: False positive when passing local var with concatenating strings
    • #3877: [apex] ApexCRUDViolation: False positive with Lists of Objects with getSObjectType().getDescribe()
  • cpp
    • #6641: [cpp]: IndexOutOfBoundsException in CPD when a duplication is at end of file with UTF8-BOM
  • java-bestpractices
    • #6692: [java] ForLoopCanBeForeach: inconsistent detection between i += 1 and i = i + 1 update forms
  • java-codestyle
    • #6239: [java] UseDiamondOperator: False positive with Guice TypeLiteral
    • #6775: [java] UselessParentheses: False negative when on the right-hand side of an assignment statement
  • java-errorprone
    • #2846: [java] New Rule: WrongTestAnnotation
    • #6743: [java] CloseResource: False positive for closeable initialized with (T) null
  • kotlin-bestpractices
    • #6732: [kotlin] New Rule: LocalVariableShadowsParameter

🚨️ API Changes

✨️ Merged pull requests

📦️ Dependency updates

📈️ Stats

PMD 7.25.0 (29-May-2026)

29 May 07:31
pmd_releases/7.25.0
418f8b7

Choose a tag to compare

29-May-2026 - 7.25.0

The PMD team is pleased to announce PMD 7.25.0.

This is a minor release.

Table Of Contents

🚀️ New and noteworthy

Updated ANTLR library to 4.13.2

We have updated the ANTLR library (parser generator) from 4.9.3 to the latest version 4.13.2,
in order to be able to use the latest version of Apex parser library.

This is an incompatible update: In case you use custom language modules based on ANTLR, you
need to make sure to regenerate all of your lexers and parsers with the new ANTLR version.

For the ANTLR based language modules, that PMD ships (kotlin and swift and various CPD modules),
this is already done.

🌟️ New and Changed Rules

New Rules

  • The new Java rule JUnitJupiterTestNoPrivateModifier find JUnit test classes and
    methods that are private. Test classes, test methods, and lifecycle methods are not required to be public,
    but they must not be private. Otherwise, they won’t be found by the test framework.
  • The new Java rule UnnecessaryBlock reports blocks that are unnecessary as
    they don't introduce a new scope. This rule helps simplify code structure by identifying and flagging
    redundant blocks that can make code harder to read and may be misleading.
  • The new Java rule VariableDeclarationUsageDistance flags local variables that are declared
    far from their usage, which can make code harder to read. The rule has a property maxDistance that allows to
    configure the maximum allowed distance between declaration and usage.
  • The new Java rule AssertStatementInTest detects usages of assert statement in tests.
    These should be replaced by framework assertion methods such as assertEquals.
    Such methods provide better error messages and make test behave correctly when running without -ea.

Changed Rules

Renamed rules and properties

Read more

PMD 7.24.0 (24-April-2026)

24 Apr 10:32
pmd_releases/7.24.0
e9787d8

Choose a tag to compare

24-April-2026 - 7.24.0

The PMD team is pleased to announce PMD 7.24.0.

This is a minor release.

Table Of Contents

🌟️ New Rules

  • The new Apex rule AvoidInterfaceAsMapKey reports Map declarations
    (fields, variables, parameters) whose key type is an interface that has at least one abstract implementing
    class defining equals or hashCode. Using such maps results in potentially duplicated map entries or
    not being able to get entries by key.
  • The new Java rule OverridingThreadRun finds overridden Thread::run methods.
    This is not recommended. Instead, implement Runnable and pass an instance to the thread constructor.

🐛️ Fixed Issues

  • apex
    • #5386: [apex] Apex files ending in "Test" are skipped with a number of rules
  • apex-errorprone
    • #6492: [apex] New rule: Prevent use of interface -> abstract class with equals/hashCode as key in Map
  • apex-security
    • #5385: [apex] ApexCRUDViolation not reported even if SOQL doesn't have permissions check on it
  • java-bestpractices
    • #4272: [java] JUnitTestsShouldIncludeAssert: False positive with assert in lambda
  • java-multithreading
    • #595: [java] New rule: Implement Runnable instead of extending Thread
  • kotlin
    • #6003: [kotlin] Support multidollar interpolation (Kotlin 2.2)

✨️ Merged pull requests

📦️ Dependency updates

  • #6515: chore: bump pmd-regression-tester from 1.6.2 to 1.7.0
  • #6552: Bump PMD from 7.22.0 to 7.23.0
  • #6564: chore(deps): bump ruby/setup-ruby from 1.295.0 to 1.299.0
  • #6565: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.7 to 1.18.8
  • #6566: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.3.0 to 13.4.0
  • #6567: chore(deps-dev): bump log4j.version from 2.25.3 to 2.25.4
  • #6569: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.7 to 1.18.8
  • #6570: chore(deps): bump org.apache.groovy:groovy from 5.0.4 to 5.0.5
  • #6571: chore(deps-dev): bump io.github.git-commit-id:git-commit-id-maven-plugin from 9.0.2 to 9.1.0
  • #6572: chore(deps): bump bigdecimal from 4.0.1 to 4.1.0 in /docs
  • #6578: chore(deps): bump marocchino/sticky-pull-request-comment from 3.0.2 to 3.0.3
  • #6579: chore(deps): bump crate-ci/typos from 1.44.0 to 1.45.0
  • #6580: chore(deps): bump ruby/setup-ruby from 1.299.0 to 1.300.0
  • #6581: chore(deps-dev): bump io.github.git-commit-id:git-commit-id-maven-plugin from 9.1.0 to 10.0.0
  • #6582: chore(deps): bump org.checkerframework:checker-qual from 3.54.0 to 4.0.0
  • #6583: chore(deps-dev): bump ant.version from 1.10.15 to 1.10.16
  • #6584: chore(deps): bump bigdecimal from 4.1.0 to 4.1.1 in /docs
  • #6588: chore(deps): bump actions/cache from 5.0.4 to 5.0.5
  • #6589: chore(deps): bump marocchino/sticky-pull-request-comment from 3.0.3 to 3.0.4
  • #6590: chore(deps): bump crate-ci/typos from 1.45.0 to 1.45.1
  • #6591: chore(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1
  • #6592: chore(deps): bump actions/create-github-app-token from 3.0.0 to 3.1.1
  • #6593: chore(deps): bump scalameta.version from 4.15.2 to 4.16.0
  • #6594: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.25.4 to 0.25.5
  • #6595: chore(deps-dev): bump com.google.guava:guava from 33.5.0-jre to 33.6.0-jre
  • #6596: chore(deps-dev): bump ant.version from 1.10.16 to 1.10.17
  • #6599: chore(deps-dev): Bump lodash from 4.17.23 to 4.18.1
  • #6600: chore(deps-dev): Bump addressable from 2.8.9 to 2.9.0
  • #6613: chore(deps): bump ruby/setup-ruby from 1.300.0 to 1.305.0
  • #6614: chore(deps): bump com.github.siom79.japicmp:japicmp-maven-plugin from 0.25.5 to 0.25.6
  • #6615: chore(deps): bump scalameta.version from 4.16.0 to 4.16.1
  • #6616: chore(deps-dev): bump org.sonarsource.scanner.maven:sonar-maven-plugin from 5.5.0.6356 to 5.6.0.6792
  • #6617: chore(deps): bump org.jsoup:jsoup from 1.22.1 to 1.22.2
  • #6618: chore(deps): bump bigdecimal from 4.1.1 to 4.1.2 in /docs

📈️ Stats

  • 82 commits
  • 14 closed tickets & PRs
  • Days since last release: 27

PMD 7.23.0 (27-March-2026)

27 Mar 11:16
pmd_releases/7.23.0
8562692

Choose a tag to compare

27-March-2026 - 7.23.0

The PMD team is pleased to announce PMD 7.23.0.

This is a minor release.

Table Of Contents

🐛️ Fixed Issues

  • core
    • #6503: [core] Links in HTML report are broken
  • java-errorprone
    • #6502: [java] CloseResource: False positive for allowedResourceMethodPatterns entries when using unqualified method calls
  • java-security
    • #6531: [java] InsecureCryptoIv: False negative with fixed IVs from array initializers

✨️ Merged pull requests

📦️ Dependency updates

  • #6476: Bump PMD from 7.21.0 to 7.22.0
  • #6479: chore(deps): bump actions/download-artifact from 7.0.0 to 8.0.0
  • #6480: chore(deps): bump actions/upload-artifact from 6.0.0 to 7.0.0
  • #6481: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.2.0 to 13.3.0
  • #6482: chore(deps): bump org.mockito:mockito-core from 5.21.0 to 5.22.0
  • #6483: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.5 to 1.18.7
  • #6484: chore(deps): bump org.yaml:snakeyaml from 2.5 to 2.6
  • #6485: chore(deps): bump org.checkerframework:checker-qual from 3.53.1 to 3.54.0
  • #6486: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.5 to 1.18.7
  • #6487: chore(deps): bump com.google.protobuf:protobuf-java from 4.33.5 to 4.34.0
  • #6490: chore: Update gems, remove github-pages
  • #6498: chore(deps): bump ruby/setup-ruby from 1.288.0 to 1.290.0
  • #6499: chore(deps-dev): bump commons-logging:commons-logging from 1.3.5 to 1.3.6
  • #6500: chore(deps-dev): bump org.apache.maven.plugins:maven-shade-plugin from 3.6.1 to 3.6.2
  • #6501: chore(deps): bump org.apache.maven.plugins:maven-resources-plugin from 3.4.0 to 3.5.0
  • #6506: chore(deps): bump actions/create-github-app-token from 2.2.1 to 3.0.0
  • #6507: chore(deps): bump actions/download-artifact from 8.0.0 to 8.0.1
  • #6508: chore(deps): bump marocchino/sticky-pull-request-comment from 2.9.4 to 3.0.2
  • #6509: chore(deps): bump ruby/setup-ruby from 1.290.0 to 1.295.0
  • #6511: chore(deps): bump org.mockito:mockito-core from 5.22.0 to 5.23.0
  • #6514: chore: bump maven from 3.9.12 to 3.9.14
  • #6516: chore: bump json from 2.19.0 to 2.19.2
  • #6548: chore(deps): bump actions/cache from 5.0.3 to 5.0.4
  • #6549: chore(deps): bump com.google.protobuf:protobuf-java from 4.34.0 to 4.34.1
  • #6551: chore: use ruby4

📈️ Stats

  • 38 commits
  • 9 closed tickets & PRs
  • Days since last release: 27

PMD 7.22.0 (27-February-2026)

27 Feb 12:03
pmd_releases/7.22.0
7f74d77

Choose a tag to compare

27-February-2026 - 7.22.0

The PMD team is pleased to announce PMD 7.22.0.

This is a minor release.

Table Of Contents

🚀️ New and noteworthy

Security fixes

  • This release fixes a stored XSS vulnerability in VBHTMLRenderer and YAHTMLRenderer via unescaped violation messages.
    Affects CI/CD pipelines that run PMD with --format vbhtml or --format yahtml on untrusted source code
    (e.g. pull requests from external contributors) and expose the HTML report as a build artifact.
    JavaScript executes in the browser context of anyone who opens the report.
    Note: The default html format is not affected by unescaped violation messages, but a similar problem
    existed with suppressed violation markers.
    If you use these reports, it is recommended to upgrade PMD.
    Reported by Smaran Chand (@smaranchand).

🌟️ New and Changed Rules

New Rules

  • The new Java rule UnnecessaryInterfaceDeclaration detects classes that
    implement interfaces that are already implemented by its superclass, and interfaces
    that extend other interfaces already declared by their superinterfaces.
    These declarations are redundant and can be removed to simplify the code.

Changed Rules

  • The rule CloseResource introduces a new property, allowedResourceMethodPatterns,
    which lets you specify method invocation patterns whose return values are resources managed externally.
    This is useful for ignoring managed resources - for example, Reader/Writer instances obtained from
    HttpServletRequest/HttpServletResponse - because the servlet container, not application code,
    is responsible for closing them. By default, the rule ignores InputStream/OutputStream/Reader/Writer
    resources returned by methods on (Http)ServletRequest and (Http)ServletResponse
    (both javax.servlet and jakarta.servlet).

🐛️ Fixed Issues

  • core
    • #6471: [core] BaseAntlrTerminalNode should return type instead of index for getTokenKind()
    • #6475: [core] Fix stored XSS in VBHTMLRenderer and YAHTMLRenderer
  • doc
    • #6396: [doc] Mention test-pmd-tool as alternative for testing
  • java-bestpractices
    • #6431: [java] UnitTestShouldIncludeAssert: False positive with SoftAssertionsExtension on parent/grandparent classes
  • java-codestyle
    • #6458: [java] New Rule: UnnecessaryInterfaceDeclaration
  • java-errorprone
    • #5787: [java] InvalidLogMessageFormat: False positive with lombok @Value generated methods
    • #6436: [java] CloseResource: Allow to ignore managed resources

🚨️ API Changes

Deprecations

✨️ Merged pull requests

📦️ Dependency updates

  • #6433: Bump PMD from 7.20.0 to 7.21.0
  • #6438: chore(deps): bump actions/cache from 5.0.2 to 5.0.3
  • #6439: chore(deps): bump ruby/setup-ruby from 1.286.0 to 1.288.0
  • #6440: chore(deps): bump scalameta.version from 4.14.6 to 4.14.7
  • #6441: chore(deps): bump org.apache.maven.plugins:maven-compiler-plugin from 3.14.1 to 3.15.0
  • #6442: chore(deps): bump org.checkerframework:checker-qual from 3.53.0 to 3.53.1
  • #6443: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.0.0 to 13.1.0
  • #6444: chore(deps): bump com.google.protobuf:protobuf-java from 4.33.4 to 4.33.5
  • #6452: chore(deps): bump actions/checkout from 6.0.1 to 6.0.2
  • #6455: chore(deps): bump org.apache.maven.plugins:maven-dependency-plugin from 3.9.0 to 3.10.0
  • #6456: chore(deps): bump com.puppycrawl.tools:checkstyle from 13.1.0 to 13.2.0
  • #6462: chore(deps): bump junit.version from 6.0.2 to 6.0.3
  • #6463: chore(deps): bump scalameta.version from 4.14.7 to 4.15.2
  • #6465: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.4 to 1.18.5
  • #6468: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.4 to 1.18.5
  • #6469: chore(deps): bump surefire.version from 3.5.4 to 3.5.5
  • #6470: chore(deps): bump org.jetbrains:annotations from 26.0.2-1 to 26.1.0
  • #6473: chore(deps): bump nokogiri to 1.19.1
  • #6474: chore(deps): bump faraday from 2.13.3 to 2.14.1

📈️ Stats

  • 66 commits
  • 16 closed tickets & PRs
  • Days since last release: 28

PMD 7.21.0 (30-January-2026)

30 Jan 09:52
pmd_releases/7.21.0
4558030

Choose a tag to compare

30-January-2026 - 7.21.0

The PMD team is pleased to announce PMD 7.21.0.

This is a minor release.

Table Of Contents

🚀️ New and noteworthy

🚀️ New: Java 26 Support

This release of PMD brings support for Java 26.

There are no new standard language features.

There is one preview language feature:

In order to analyze a project with PMD that uses these preview language features,
you'll need to select the new language version 26-preview:

pmd check --use-version java-26-preview ...

Note: Support for Java 24 preview language features have been removed. The version "24-preview"
is no longer available.

Build Requirement is Java 21

From now on, Java 21 or newer is required to build PMD. PMD itself still remains compatible with Java 8,
so that it still can be used in a pure Java 8 environment. This allows us to use the latest
checkstyle version during the build.

CPD

  • The Apex module now supports suppression through CPD-ON/CPD-OFF comment pairs. See #6417

🌟️ New and Changed Rules

New Rules

  • The new Java rule PublicMemberInNonPublicType detects public members (such as methods
    or fields) within non-public types. Non-public types should not declare public members, as their effective
    visibility is limited, and using the public modifier can create confusion.
  • The new Java rule UnsupportedJdkApiUsage flags the use of unsupported and non-portable
    JDK APIs, including sun.* packages, sun.misc.Unsafe, and jdk.internal.misc.Unsafe. These APIs are unstable,
    intended for internal use, and may change or be removed. The rule complements Java compiler warnings by
    highlighting such usage during code reviews and encouraging migration to official APIs like VarHandle and
    the Foreign Function & Memory API.

Changed Rules

The following rules have been changed to use a consistent implementation of enum based
rule properties:

  • The property checkAddressTypes of rule AvoidUsingHardCodedIP has changed:
    • Instead of IPv4 use ipv4
    • Instead of IPv6 use ipv6
    • Instead of IPv4 mapped IPv6 use ipv4MappedIpv6
    • The old values still work, but you'll see a deprecation warning.
  • The property nullCheckBranch of rule ConfusingTernary has changed:
    • Instead of Any use any
    • Instead of Then use then
    • Instead of Else use else
    • The old values still work, but you'll see a deprecation warning.
  • The property typeAnnotations of rule ModifierOrder has changed:
    • Instead of ontype use onType
    • Instead of ondecl use onDecl
    • The old values still work, but you'll see a deprecation warning.
  • The values of the properties of rule CommentRequired have changed:
    • Instead of Required use required
    • Instead of Ignored use ignored
    • Instead of Unwanted use unwanted
    • The old values still work, but you'll see a deprecation warning.

Deprecated Rules

🐛️ Fixed Issues

  • core
    • #6184: [core] Consistent implementation of enum properties
  • apex
    • #6417: [apex] Support CPD suppression with "CPD-OFF" & "CPD-ON"
  • apex-codestyle
    • #6349: [apex] FieldDeclarationsShouldBeAtStart: False positive with properties
  • cli
    • #6290: [cli] Improve Designer start script
  • java
    • #5871: [java] Support Java 26
    • #6364: [java] Parse error with yield lambda inside switch
  • java-design
    • #6231: [java] New Rule: PublicMemberInNonPublicType
  • java-errorprone
    • #3601: [java] InvalidLogMessageFormat: False positive when final parameter is Supplier<Throwable>
    • #5882: [java] UnconditionalIfStatement: False negative when true/false is not literal but local variable
    • #5923: [java] New Rule: Catch usages of sun.misc.Unsafe or jdk.internal.misc.Unsafe
  • java-performance
    • #3857: [java] InsufficientStringBufferDeclaration: False negatives with String constants

🚨️ API Changes

Deprecations

Read more

PMD 7.20.0 (30-December-2025)

30 Dec 15:44
pmd_releases/7.20.0
fa478ec

Choose a tag to compare

30-December-2025 - 7.20.0

The PMD team is pleased to announce PMD 7.20.0.

This is a minor release.

Table Of Contents

🌟️ Changed Rules

  • The Java rule OnlyOneReturn has a new property ignoredMethodNames. This property by
    default is set to compareTo and equals, thus this rule now by default allows multiple return statements
    for these methods. To restore the old behavior, simply set this property to an empty value.

🐛️ Fixed Issues

  • core
    • #6330: [core] "Unable to create ValueRepresentation" when using @LiteralText (XPath)
  • java
    • #6234: [java] Parser fails to parse switch expressions in super() constructor calls
    • #6299: [java] Fix grammar of switch label
  • java-bestpractices
    • #4282: [java] GuardLogStatement: False positive when guard is not a direct parent
    • #6028: [java] UnusedPrivateMethod: False positive with raw type for generic method
    • #6257: [java] UnusedLocalVariable: False positive with instanceof pattern guard
    • #6291: [java] EnumComparison: False positive for any object when object.equals(null)
    • #6328: [java] UnusedLocalVariable: False positive for pattern variable in for-each without braces
  • java-codestyle
    • #4257: [java] OnlyOneReturn: False positive with equals method
    • #5043: [java] LambdaCanBeMethodReference: False positive on overloaded methods
    • #6237: [java] UnnecessaryCast: ContextedRuntimeException when parsing switch expression with lambdas
    • #6279: [java] EmptyMethodInAbstractClassShouldBeAbstract: False positive for final empty methods
    • #6284: [java] UnnecessaryConstructor: False positive for JavaDoc-bearing constructor
  • java-errorprone
    • #6276: [java] NullAssignment: False positive when assigning null to a final field in a constructor
    • #6343: [java] MissingStaticMethodInNonInstantiatableClass: False negative when method in nested class returns null
  • java-performance
    • #4158: [java] BigIntegerInstantiation: False negative with compile-time constant
    • #4910: [java] ConsecutiveAppendsShouldReuse: False positive within if-statement without curly braces
    • #5877: [java] AvoidArrayLoops: False negative when break inside switch statement
  • maintenance
    • #6230: [core] Single module snapshot build fails

🚨️ API Changes

Experimental API

✨️ Merged pull requests

📦️ Dependency updates

  • #6286: Bump PMD from 7.18.0 to 7.19.0
  • #6300: chore(deps): bump actions/checkout from 6.0.0 to 6.0.1
  • #6301: chore(deps): bump org.checkerframework:checker-qual from 3.52.0 to 3.52.1
  • #6302: chore(deps): bump org.apache.maven.plugins:maven-resources-plugin from 3.3.1 to 3.4.0
  • #6303: chore(deps-dev): bump net.bytebuddy:byte-buddy from 1.18.1 to 1.18.2
  • #6304: chore(deps): bump com.puppycrawl.tools:checkstyle from 12.1.2 to 12.2.0
  • #6305: chore(deps): bump org.sonarsource.scanner.maven:sonar-maven-plugin from 5.3.0.6276 to 5.4.0.6343
  • #6306: chore(deps): bump webrick from 1.9.1 to 1.9.2 in /docs
  • #6318: chore(deps): bump actions/create-github-app-token from 2.2.0 to 2.2.1
  • #6319: chore(deps): bump actions/setup-java from 5.0.0 to 5.1.0
  • #6320: chore(deps): bump ruby/setup-ruby from 1.268.0 to 1.269.0
  • #6321: chore(deps-dev): bump net.bytebuddy:byte-buddy-agent from 1.18.1 to 1.18.2
  • #6323: chore(deps): bump com.google.protobuf:protobuf-java from 4.33.1 to 4.33.2
  • #6324: chore(deps): bump io.github.apex-dev-tools:apex-ls_2.13 from 6.0.1 to 6.0.2
  • #6325: chore(deps): bump org.apache.maven.plugins:maven-assembly-plugin from 3.7.1 to 3.8.0
  • #6329: chore(deps): bump org.mozilla:rhino from 1.7.15 to 1.7.15.1
  • #6331: chore(deps): bump actions/upload-artifact from 5.0.0 to 6.0.0
  • #6332: chore(deps): bump org.mockito:mockito-core from 5.20.0 to 5.21.0
  • #6333: chore(deps): bump actions/download-artifact from 6.0.0 to 7.0.0
  • #6334: chore(deps): bump ruby/setup-ruby ...
Read more

PMD 7.19.0 (28-November-2025)

28 Nov 11:36
pmd_releases/7.19.0
2373452

Choose a tag to compare

28-November-2025 - 7.19.0

The PMD team is pleased to announce PMD 7.19.0.

This is a minor release.

Table Of Contents

🚀️ New and noteworthy

Updated PMD Designer

This PMD release ships a new version of the pmd-designer.
For the changes, see PMD Designer Changelog (7.19.0)
and PMD Designer Changelog (7.19.1).

🌟️ New and Changed Rules

New Rules

  • The new Apex rule AvoidFutureAnnotation finds usages of the @Future
    annotation. It is a legacy way to execute asynchronous Apex code. New code should implement
    the Queueable interface instead.
  • The new Java rule EnumComparison finds usages of equals() on
    enum constants or values. Enums should be compared directly with == instead of equals() which
    has some advantages (e.g. static type checking at compile time).
  • The new Apex rule NcssCount replaces the four rules "ExcessiveClassLength",
    "NcssConstructorCount", "NcssMethodCount", and "NcssTypeCount". The new rule uses the metrics framework
    to achieve the same. It has two properties, to define the report level for method and class sizes separately.
    Constructors and methods are considered the same.
    The rule has been added to the quickstart ruleset.
    Note: The new metric is implemented more correct than in the old rules. E.g. it considers now also
    switch statements and correctly counts if-statements only once and ignores method calls that are
    part of an expression and not a statement on their own. This leads to different numbers. Keep in mind,
    that NCSS counts statements and not lines of code. Statements that are split on multiple lines are
    still counted as one.
  • The new PL/SQL rule NcssCount replaces the rules "ExcessiveMethodLength",
    "ExcessiveObjectLength", "ExcessivePackageBodyLength", "ExcessivePackageSpecificationLength",
    "ExcessiveTypeLength", "NcssMethodCount" and "NcssObjectCount". The new rule uses the metrics framework
    to achieve the same. It has two properties, to define the report level for method and object sizes separately.
    Note: the new metric is implemented more correct than in the old rules, so that the actual numbers of
    the NCSS metric from the old rules might be different from the new rule "NcssCount". Statements that are
    split on multiple lines are still counted as one.

Deprecated Rules

🐛️ Fixed Issues

  • core
    • #4767: [core] Deprecate old symboltable API
  • apex-bestpractices
    • #6203: [apex] New Rule: Avoid Future Annotation
  • apex-design
    • #2128: [apex] Merge NCSS count rules for Apex
  • java
    • #5689: [java] Members of record should be in scope in record header
    • #6256: [java] java.lang.IllegalArgumentException: Invalid target type of type annotation for method or ctor type annotation: 19
  • java-bestpractices
    • #5820: [java] GuardLogStatement recognizes that a string is a compile-time constant expression only if at first position
    • #6188: [java] UnitTestShouldIncludeAssert false positive when TestNG @Test.expectedException present
    • #6193: [java] New Rule: Always compare enum values with ==
  • java-codestyle
    • #6053: [java] ModifierOrder false-positives with type annotations and type parameters (typeAnnotations = anywhere)
  • java-errorprone
    • #4742: [java] EmptyFinalizer should not trigger if finalize method is final and class is not
    • #6072: [java] OverrideBothEqualsAndHashCodeOnComparable should not be required for record classes
    • #6092: [java] AssignmentInOperand false positive in 7.17.0 for case blocks in switch statements
    • #6096: [java] OverrideBothEqualsAndHashCodeOnComparable on class with lombok.EqualsAndHashCode annotation
    • #6199: [java] AssignmentInOperand: description of property allowIncrementDecrement is unclear
    • #6273: [java] TestClassWithoutTestCases documentation does not mention test prefixes
  • java-performance
    • #4577: [java] UseArraysAsList with condition in loop
    • #5071: [java] UseArraysAsList should not warn when elements are skipped in array
  • plsql-design
    • #4326: [plsql] Merge NCSS count rules for PL/SQL
  • maintenance
    • #5701: [core] net.sourceforge.pmd.cpd.SourceManager has public methods

🚨️ API Changes

Deprecations

  • core
    • net.sourceforge.pmd.lang.symboltable: All classes in this package are deprecated.
      The symbol table and type resolution implementation for Java has been rewritten from scratch
      for PMD 7.0.0. This package is the remains of the old symbol table API, that is only used by
      PL/SQL. For PMD 8.0.0 all these classes will be removed from pmd-core.
  • apex
Read more

PMD 7.18.0 (31-October-2025)

31 Oct 08:59
pmd_releases/7.18.0
c37a323

Choose a tag to compare

31-October-2025 - 7.18.0

The PMD team is pleased to announce PMD 7.18.0.

This is a minor release.

Table Of Contents

🚀️ New and noteworthy

Build Requirement is Java 17

From now on, Java 17 or newer is required to build PMD. PMD itself still remains compatible with Java 8,
so that it still can be used in a pure Java 8 environment. This allows us to use the latest
checkstyle version during the build.

🌟️ New and Changed Rules

New Rules

  • The new Java rule IdenticalConditionalBranches finds conditional statements
    that do the same thing when the condition is true and false. This is either incorrect or redundant.
  • The new Java rule LabeledStatement finds labeled statements in code.
    Labels make control flow difficult to understand and should be avoided. By default, the rule allows labeled
    loops (do, while, for). But it has a property to flag also those labeled loops.
  • The new Java rule UnusedLabel finds unused labels which are unnecessary and
    only make the code hard to read. This new rule will be part of the quickstart ruleset.

Changed Rules

  • ConfusingTernary has a new property nullCheckBranch to control, whether null-checks
    should be allowed (the default case) or should lead to a violation.
  • AvoidCatchingGenericException is now configurable with the new property
    typesThatShouldNotBeCaught.
    ⚠️ The rule has also been moved from category "Design" to category "Error Prone". If you are currently bulk-adding
    all the rules from the "Design" category into your custom ruleset, then you need to add the rule explicitly
    again (otherwise it won't be included anymore):
    <rule ref="category/java/errorprone.xml/AvoidCatchingGenericException" />

Deprecated Rules

🐛️ Fixed Issues

  • general
    • #4714: [core] Allow trailing commas in multivalued properties
    • #5873: [ci] Run integration test with Java 25
    • #6012: [pmd-rulesets] Rulesets should be in alphabetical order
    • #6073: [doc] Search improvements
    • #6097: [doc] Add PMD versions dropdown
    • #6098: [doc] Add a copy URL button
    • #6101: [doc] Highlight current header in TOC
    • #6149: [doc] Reproducible Build Documentation is outdated - PMD is now built using Java 17
    • #6150: [core] Reduce memory usage of CPD's MatchCollector
  • apex
    • #5935: [apex] @SuppressWarnings - allow whitespace around comma when suppressing multiple rules
  • apex-design
    • #6022: [apex] ExcessiveClassLength/ExcessiveParameterList include the metric in the message
  • apex-documentation
    • #6189: [apex] ApexDoc rule doesn't match published Salesforce ApexDoc specification
  • java
    • #4904: [java] Renderers output wrong class qualified name for nested classes
    • #6127: [java] Incorrect variable name in violation
    • #6132: [java] Implement main method launch protocol priorities
    • #6146: [java] ClassCastException: class InferenceVarSym cannot be cast to class JClassSymbol
  • java-bestpractices
    • #2928: [java] New rules about labeled statements
    • #4122: [java] CheckResultSet false-positive with local variable
    • #6124: [java] UnusedLocalVariable: fix false negatives in pattern matching
    • #6169: [java] AvoidUsingHardCodedIP: violation message should mention the hard coded address
    • #6171: [java] AvoidUsingHardCodedIP: fix false positive for IPv6
  • java-codestyle
    • #5919: [java] ClassNamingConventions: Include integration tests in testClassPattern by default
    • #6004: [java] Make ConfusingTernary != null configurable
    • #6029: [java] Fix UnnecessaryCast false-negative in method calls
    • #6057: [java] ModifierOrder false positive on "abstract sealed class"
    • #6079: [java] IdenticalCatchBranches: False negative for overriden method calls
    • #6123: [java] UselessParentheses FP around switch expression
    • #6131: [java] ModifierOrder: wrong enum values documented, indirectly causing xml parse errors
  • java-design
    • #1499: [java] AvoidDeeplyNestedIfStmts violations can be unintentionally undetected
    • #5569: [java] ExcessivePublicCount should report number of public "things"
  • java-documentation
    • #6058: [java] DanglingJavadoc FP in module-info files
    • #6103: [java] DanglingJavadoc false positive on record compact constructors
  • java-errorprone
    • #5042: [java] CloseResource false-positive on Pattern Matching with instanceof
    • #5878: [java] DontUseFloatTypeForLoopIndices false-negative if variable is declared before loop
    • #6038: [java] Merge AvoidCatchingNPE and AvoidCatchingThrowable into AvoidCatchingGenericException
    • #6055: [java] UselessPureMethodCall false positive with AtomicInteger::getAndIncrement
    • #6060: [java] UselessPureMethodCall false positive on ZipInputStream::getNextEntry
    • #6075: [java] AssignmentInOperand false positive with lambda expressions
    • #6083: [java] New rule IdenticalConditionalBranches
  • java-multithreading
    • #5880: [java] DoubleCheckedLocking is not detected if more than 1 assignment or more than 2 if statements
  • java-performance
    • #6172: [java] InefficientEmptyStringCheck should include String#strip
  • java-security
    • #6191: [java] HardCodedCryptoKey: NPE when constants from parent class are used
  • plsql-design
    • #6077: [plsql] Excessive*/Ncss*Count/NPathComplexity include the metric

🚨️ API Changes

Deprecations

✨️ Merged pull requests

Read more

PMD 7.17.0 (12-September-2025)

12 Sep 08:10
pmd_releases/7.17.0
d2942d5

Choose a tag to compare

12-September-2025 - 7.17.0

The PMD team is pleased to announce PMD 7.17.0.

This is a minor release.

Table Of Contents

🚀 New and noteworthy

✨ New Rules

This release brings several new rules for both Java and Apex. Please try them out
and submit feedback on our issue tracker!

  • The new apex rule AnnotationsNamingConventions enforces that annotations
    are used consistently in PascalCase.
    The rule is referenced in the quickstart.xml ruleset for Apex.
  • The new java rule TypeParameterNamingConventions replaces the now deprecated rule
    GenericsNaming. The new rule is configurable and checks for naming conventions of type parameters in
    generic types and methods. It can be configured via a regular expression.
    By default, this rule uses the standard Java naming convention (single uppercase letter).
    The rule is referenced in the quickstart.xml ruleset for Java.
  • The new java rule OverrideBothEqualsAndHashCodeOnComparable finds missing
    hashCode() and/or equals() methods on types that implement Comparable. This is important if
    instances of these classes are used in collections. Failing to do so can lead to unexpected behavior in sets
    which then do not conform to the Set interface. While the Set interface relies on
    equals() to determine object equality, sorted sets like TreeSet use
    compareTo() instead. The same issue can arise when such objects are used
    as keys in sorted maps.
    This rule is very similar to OverrideBothEqualsAndHashcode which has always been
    skipping Comparable and only reports if one of the two methods is missing. The new rule will also report,
    if both methods (hashCode and equals) are missing.
    The rule is referenced in the quickstart.xml ruleset for Java.
  • The new java rule UselessPureMethodCall finds method calls of pure methods
    whose result is not used. Ignoring the result of such method calls is likely as mistake as pure
    methods are side effect free.
    The rule is referenced in the quickstart.xml ruleset for Java.
  • The new java rule RelianceOnDefaultCharset finds method calls that
    depend on the JVM's default charset. Using these method without specifying the charset explicitly
    can lead to unexpected behavior on different platforms.
  • Thew new java rule VariableCanBeInlined finds local variables that are
    immediately returned or thrown. This rule replaces the old rule UnnecessaryLocalBeforeReturn
    which only considered return statements. The new rule also finds unnecessary local variables
    before throw statements.
    The rule is referenced in the quickstart.xml ruleset for Java.
  • The new java rule CollectionTypeMismatch detects calls to
    collection methods where we suspect the types are incompatible. This happens for instance
    when you try to remove a String from a Collection<Integer>: although it is allowed
    to write this because remove takes an Object parameter, it is most likely a mistake.
    This rule is referenced in the quickstart.xml ruleset for Java.
  • The new java rule DanglingJavadoc finds Javadoc comments that
    do not belong to a class, method or field. These comments are ignored by the Javadoc tool
    and should either be corrected or removed.
    The rule is referenced in the quickstart.xml ruleset for Java.
  • The new java rule ModifierOrder (codestyle) finds incorrectly ordered modifiers
    (e.g., static public instead of public static). It ensures modifiers appear in the correct order as
    recommended by the Java Language Specification.

Deprecated Rules

CPD: New Markdown Report Format

This PMD version ships with a simple Markdown based output format for CPD. It outputs all duplications
one after another including the code snippets as code blocks.
See Report formats for CPD.

🐛 Fixed Issues

  • apex-codestyle
    • #5650: [apex] New Rule: AnnotationsNamingConventions
  • core
    • #4721: [core] chore: Enable XML rule MissingEncoding in dogfood ruleset
    • #5849: [core] Support Markdown Output for CPD Reports
    • #5958: [core] CSVRenderer: Add begin and end for line and columns (default off)
  • java
    • #5874: [java] Update java regression tests with Java 25 language features
    • #5960: [java] Avoid/reduce duplicate error messages for some rules
    • #6014: [java] Crash when encountering a java comment at the end of a file
  • java-bestpractices
    • #2186: [java] New Rule: RelianceOnDefaultCharset
    • #4500: [java] AvoidReassigningLoopVariables - false negatives within for-loops and skip allowed
    • #4770: [java] UnusedFormalParameter should ignore public constructor as same as method
    • #5198: [java] CheckResultSet false-positive with local variable checked in a while loop
  • java-codestyle
    • #972: [java] Improve naming conventions rules
    • #4916: [java] UseExplicitTypes: cases where 'var' should be unobjectionable
    • #5601: [java] New Rule: ModifierOrder
    • #5770: [java] New Rule: VariableCanBeInlined: Local variables should not be declared and then immediately returned or thrown
    • #5922: [java] New Rule: TypeParameterNamingConventions
    • #5948: [java] UnnecessaryBoxing false positive when calling List.remove(int)
    • #5982: [java] More detailed message for the UselessParentheses rule
  • java-design
    • #4911: [java] AvoidRethrowingException should allow rethrowing exception subclasses
    • #5023: [java] UseUtilityClass implementation hardcodes a message instead of using the one defined in the XML
  • java-documentation
    • #5916: [java] New Rule: DanglingJavadoc
  • java-errorprone
    • #3401: [java] Improve AvoidUsingOctalValues documentation
    • #3434: [java] False negatives in AssignmentInOperand Rule
    • #5837: [java] New Rule: OverrideBothEqualsAndHashCodeOnComparable
    • #5881: [java] AvoidLosi...
Read more