Skip to content

NPE during display-discovered-jdk-toolchains goal in ToolchainDiscoverer.discoverToolchains() #191

Description

@chabala

Affected version

3.3.0

Bug description

This is similar to #113 and #119 , the cause just moves around.

This time it's here:

ToolchainModel tc = getToolchainModel(s);
flags.getOrDefault(s, Collections.emptyMap())
.forEach((k, v) -> tc.getProvides().setProperty(k, v));
String version = tc.getProvides().getProperty(VERSION);

ToolchainModel tc is set to null on line 152, and dereferenced on line 155.

I have an install of JDK 1.5 at /usr/lib/jvm/jdk1.5.0_22/ which I use to trigger these issues, should you want to replicate.

Command issued mvn -X org.apache.maven.plugins:maven-toolchains-plugin:3.3.0:display-discovered-jdk-toolchains

Output:

[DEBUG] Loading mojo org.apache.maven.plugins:maven-toolchains-plugin:3.3.0:display-discovered-jdk-toolchains from plugin realm ClassRealm[plugin>org.apache.maven.plugins:maven-toolchains-plugin:3.3.0, parent: sun.misc.Launcher$AppClassLoader@7852e922]
[DEBUG] Configuring mojo execution 'org.apache.maven.plugins:maven-toolchains-plugin:3.3.0:display-discovered-jdk-toolchains:default-cli' with basic configurator -->
[DEBUG]   (f) comparator = lts,current,env,version,vendor
[DEBUG] -- end configuration --
[INFO] Found 3 possible jdks: [/usr/lib/jvm/adoptopenjdk-11-hotspot-amd64, /usr/lib/jvm/jdk1.5.0_22, /usr/lib/jvm/adoptopenjdk-8-hotspot-amd64]
[DEBUG] JDK toolchain discovered at /usr/lib/jvm/jdk1.5.0_22 will be ignored: could not obtain java.version
[WARNING] Error discovering toolchains: java.lang.NullPointerException
java.lang.NullPointerException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0 (Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance (NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance (DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance (Constructor.java:423)
    at java.util.concurrent.ForkJoinTask.getThrowableException (ForkJoinTask.java:598)
    at java.util.concurrent.ForkJoinTask.reportException (ForkJoinTask.java:677)
    at java.util.concurrent.ForkJoinTask.invoke (ForkJoinTask.java:735)
    at java.util.stream.Nodes.collect (Nodes.java:328)
    at java.util.stream.ReferencePipeline.evaluateToNode (ReferencePipeline.java:109)
    at java.util.stream.AbstractPipeline.evaluate (AbstractPipeline.java:541)
    at java.util.stream.SortedOps$OfRef.opEvaluateParallel (SortedOps.java:157)
    at java.util.stream.AbstractPipeline.opEvaluateParallelLazy (AbstractPipeline.java:705)
    at java.util.stream.AbstractPipeline.sourceSpliterator (AbstractPipeline.java:432)
    at java.util.stream.AbstractPipeline.evaluate (AbstractPipeline.java:233)
    at java.util.stream.ReferencePipeline.collect (ReferencePipeline.java:566)
    at org.apache.maven.plugins.toolchain.jdk.ToolchainDiscoverer.discoverToolchains (ToolchainDiscoverer.java:162)
    at org.apache.maven.plugins.toolchain.jdk.DisplayDiscoveredJdkToolchainsMojo.execute (DisplayDiscoveredJdkToolchainsMojo.java:65)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:906)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:206)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:283)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:226)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:407)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:348)
Caused by: java.lang.NullPointerException
    at org.apache.maven.plugins.toolchain.jdk.ToolchainDiscoverer.lambda$discoverToolchains$4 (ToolchainDiscoverer.java:155)
    at java.util.stream.ReferencePipeline$3$1.accept (ReferencePipeline.java:193)
    at java.util.HashMap$KeySpliterator.forEachRemaining (HashMap.java:1556)
    at java.util.stream.AbstractPipeline.copyInto (AbstractPipeline.java:482)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:472)
    at java.util.stream.Nodes$CollectorTask.doLeaf (Nodes.java:2183)
    at java.util.stream.Nodes$CollectorTask.doLeaf (Nodes.java:2149)
    at java.util.stream.AbstractTask.compute (AbstractTask.java:327)
    at java.util.concurrent.CountedCompleter.exec (CountedCompleter.java:731)
    at java.util.concurrent.ForkJoinTask.doExec (ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask (ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker (ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run (ForkJoinWorkerThread.java:175)
[INFO] Discovered 0 JDK toolchains:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.487 s
[INFO] Finished at: 2026-07-28T20:25:55-05:00
[INFO] ------------------------------------------------------------------------

What I think should happen: even if the version can't be determined for a potential JDK, the others should be found.

I also see a lot of Java streams, parallelStream, filter and mapping in this code, but also returning null and (missed) null checks. Why not embrace Optional if you're going to use the other functional patterns? No more nulls, no more NPEs, return Optional.empty().

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions