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).

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