Skip to content

Version comparator in ToolchainDiscoverer uses lexicographic String.compareTo instead of numeric version comparison #166

Description

@elharo

Summary

The version() comparator in ToolchainDiscoverer.java uses String.compareTo() for version comparison, which is lexicographic rather than numeric. This produces incorrect sort orders for JDK versions with different digit counts.

Location

ToolchainDiscoverer.java:290-306

https://github.com/apache/maven-toolchains-plugin/blob/master/src/main/java/org/apache/maven/plugins/toolchain/jdk/ToolchainDiscoverer.java#L290-L306

Code

Comparator<ToolchainModel> version() {
    return comparing((ToolchainModel tc) -> tc.getProvides().getProperty(VERSION), (v1, v2) -> {
                String[] a = v1.split("\\.");
                String[] b = v2.split("\\.");
                int length = Math.min(a.length, b.length);
                for (int i = 0; i < length; i++) {
                    String oa = a[i];
                    String ob = b[i];
                    if (!Objects.equals(oa, ob)) {
                        if (oa == null || ob == null) {
                            return oa == null ? -1 : 1;
                        }
                        int v = oa.compareTo(ob);
                        if (v != 0) {
                            return v;
                        }
                    }
                }
                return a.length - b.length;
            })
            .reversed();
}

Problem

String.compareTo() compares strings lexicographically, not numerically. This causes incorrect ordering:

  • "8" > "11" (because '8' > '1' in ASCII) -- WRONG, 8 < 11
  • "8" > "17" -- WRONG
  • "9" > "10" -- WRONG
  • "10" > "8" -- WRONG

The .reversed() at the end means higher versions should sort first, but this bug corrupts the ordering for any comparison between single-digit and multi-digit major versions.

Impact

JDK toolchain discovery and selection produces wrong sort order, which means select-jdk-toolchain may choose a suboptimal JDK. For example, if JDK 8 and JDK 11 are both available and match requirements, JDK 8 could be incorrectly preferred over JDK 11.

Suggested Fix

Use proper numeric version comparison (e.g., split segments and compare each segment as integers, or use a dedicated version comparator like ComparableVersion from Maven artifact API).

Activity

  1. added theissue type on Jul 22, 2026
  2. reopened this on Jul 22, 2026
  3. elharo commented on Jul 22, 2026

    @elharo
    ContributorAuthor

    a dedicated version comparator like ComparableVersion from Maven artifact API is not appropriate here. That compares Maven artifact version strings. This needs to compare JDK version strings which are not quite the same. Custom code is required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:majorMajor loss of function

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions