30 January 2026
The PMD team is pleased to announce PMD 7.21.0.
This is a minor release.
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.
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-ON/CPD-OFF comment pairs. See #6417PublicMemberInNonPublicType 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.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.The following rules have been changed to use a consistent implementation of enum based rule properties:
checkAddressTypes of rule AvoidUsingHardCodedIP has changed:
IPv4 use ipv4IPv6 use ipv6IPv4 mapped IPv6 use ipv4MappedIpv6nullCheckBranch of rule ConfusingTernary has changed:
Any use anyThen use thenElse use elsetypeAnnotations of rule ModifierOrder has changed:
ontype use onTypeondecl use onDeclCommentRequired have changed:
Required use requiredIgnored use ignoredUnwanted use unwantedDontImportSun has been deprecated. It is replaced by
UnsupportedJdkApiUsage.MetricOption#valueName: When metrics are used for (rule) properties,
then the conventional enum mapping (from SCREAMING_SNAKE_CASE to camelCase) will be used for the enum values.
See conventionalEnumListProperty.PropertyFactory:
enumProperty(String, Map). Use
conventionalEnumProperty instead.enumProperty(String, Class). Use
conventionalEnumProperty instead.enumProperty(String, Class, Function). Use
conventionalEnumProperty instead.enumListProperty(String, Map). Use
conventionalEnumListProperty instead.enumListProperty(String, Class, Function). Use
conventionalEnumListProperty instead.AvoidBranchingStatementAsLastInLoopRule#CHECK_FOR. This constant should
have never been public.AvoidBranchingStatementAsLastInLoopRule#CHECK_DO. This constant should
have never been public.AvoidBranchingStatementAsLastInLoopRule#CHECK_WHILE. This constant should
have never been public.AvoidBranchingStatementAsLastInLoopRule#CHECK_BREAK_LOOP_TYPES. This property
descriptor should have been private. It won’t be used anymore. Use getPropertyDescriptor
on the rule to retrieve the property descriptor.AvoidBranchingStatementAsLastInLoopRule#CHECK_CONTINUE_LOOP_TYPES. This property
descriptor should have been private. It won’t be used anymore. Use getPropertyDescriptor
on the rule to retrieve the property descriptor.AvoidBranchingStatementAsLastInLoopRule#CHECK_RETURN_LOOP_TYPES. This property
descriptor should have been private. It won’t be used anymore. Use getPropertyDescriptor
on the rule to retrieve the property descriptor.AvoidBranchingStatementAsLastInLoopRule#check.
This method should have been private and will be internalized.AvoidBranchingStatementAsLastInLoopRule#hasPropertyValue.
This method should have been private and will be internalized.AvoidBranchingStatementAsLastInLoopRule#checksNothing.
This method should have been private and will be internalized.ClassFanOutOption#valueName,
CycloOption#valueName,
NcssOption#valueNameAbstractMetricTestRule#optionMappings. No extra mapping is required anymore.
The MetricOption enum values are used. See
AbstractMetricTestRule(Metric, Class)
to provide the enum at construction time.