Skip to content

DefaultModelValidator is not thread safe #11618

@gabrielgiussi

Description

@gabrielgiussi

Affected version

3.8.7

Bug description

DefaultModelValidator is not thread safe, and could cause the following exception

java.lang.ClassCastException: class java.util.HashMap$Node cannot be cast to class java.util.HashMap$TreeNode (java.util.HashMap$Node and java.util.HashMap$TreeNode are in module java.base of loader 'bootstrap')

In my case this is happening through leiningen, when we switched the aether dependency collector strategy to bf (which uses multiple threads), aka aether.dependencyCollector.impl=bf.

The stacktrace looks similar to this one reported for netbeans

INFO [org.netbeans.modules.maven.problems.MavenModelProblemsProvider]: Exception thrown while loading maven project at C:\[PATH_TO_MAVEN_MODULE]@4ab62a4e:92fc990
java.lang.ClassCastException: class java.util.HashMap$Node cannot be cast to class java.util.HashMap$TreeNode (java.util.HashMap$Node and java.util.HashMap$TreeNode are in module java.base of loader 'bootstrap')
	at java.base/java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1900)
	at java.base/java.util.HashMap$TreeNode.putTreeVal(HashMap.java:2079)
	at java.base/java.util.HashMap.putVal(HashMap.java:634)
	at java.base/java.util.HashMap.put(HashMap.java:608)
	at java.base/java.util.HashSet.add(HashSet.java:220)
	at org.apache.maven.model.validation.DefaultModelValidator.validateId(DefaultModelValidator.java:852)
	at org.apache.maven.model.validation.DefaultModelValidator.validateEffectiveDependency(DefaultModelValidator.java:664)
	at org.apache.maven.model.validation.DefaultModelValidator.validateEffectiveDependencies(DefaultModelValidator.java:588)
	at org.apache.maven.model.validation.DefaultModelValidator.validateEffectiveModel(DefaultModelValidator.java:378)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:564)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:454)
	at org.apache.maven.model.building.DefaultModelBuilder.importDependencyManagement(DefaultModelBuilder.java:1381)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:544)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:454)
	at org.apache.maven.model.building.DefaultModelBuilder.importDependencyManagement(DefaultModelBuilder.java:1381)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:544)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:454)
	at org.apache.maven.model.building.DefaultModelBuilder.importDependencyManagement(DefaultModelBuilder.java:1381)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:544)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:454)
	at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:267)
	at org.netbeans.modules.maven.embedder.impl.NBModelBuilder.build(NBModelBuilder.java:53)
	at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom(DefaultArtifactDescriptorReader.java:293)
	at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor(DefaultArtifactDescriptorReader.java:171)
	at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.resolveCachedArtifactDescriptor(DefaultDependencyCollector.java:538)
	at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.getArtifactDescriptorResult(DefaultDependencyCollector.java:523)
	at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:410)
	at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:362)
	at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.process(DefaultDependencyCollector.java:349)
	at org.eclipse.aether.internal.impl.collect.DefaultDependencyCollector.collectDependencies(DefaultDependencyCollector.java:254)
	at org.eclipse.aether.internal.impl.DefaultRepositorySystem.collectDependencies(DefaultRepositorySystem.java:284)
	at org.apache.maven.project.DefaultProjectDependenciesResolver.resolve(DefaultProjectDependenciesResolver.java:170)
	at org.apache.maven.project.DefaultProjectBuilder.resolveDependencies(DefaultProjectBuilder.java:227)
	at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:200)
	at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:124)

There is also this ticket related to clojure tools-deps build mechanism, where they reach the same conclusion

DefaultModelValidator appears to just not be thread-safe.

This is where the exception is thrown (maven 3.8.4):
https://github.com/apache/maven/blob/maven-3.8.4/maven-model-
builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java#L848

validIds is a private HashSet.

The version 3.8.7 reported is about maven-model-builder, which is the version leiningen 2.11.2 is using.

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