Search code examples
javaxstreamoptaplannerconcurrentmodification

Getting a "rare" ConcurrentModificationException during program execution


I am creating a program using Optaplanner, and I keep getting this exception but only on rare occassions, most of the time I can execute my program without problems, and it's hard to recreate the issue, since it only happens sometimes...

Exception in thread "main" java.util.ConcurrentModificationException: java.util.ConcurrentModificationException
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	...
 	at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildDroolsScoreDirectorFactory(ScoreDirectorFactoryConfig.java:503)
	at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildScoreDirectorFactory(ScoreDirectorFactoryConfig.java:331)
	at org.optaplanner.core.config.solver.SolverConfig.buildSolver(SolverConfig.java:220)
	at org.optaplanner.core.impl.solver.AbstractSolverFactory.buildSolver(AbstractSolverFactory.java:61)
	at org.avalin.optaplanner.main.EmployeeRoster.buildEvaluationSolver(EmployeeRoster.java:247)
	at org.avalin.optaplanner.main.EmployeeRoster.main(EmployeeRoster.java:82)
Caused by: java.util.ConcurrentModificationException
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1138)
  ...
  	at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
	at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:747)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:283)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1603)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)

Here's the buildEvaluationSolver method that it seems to happen at:

private static Solver buildEvaluationSolver()
{
    SolverFactory solverFactory = SolverFactory.createFromXmlResource(EVALUATION_CONFIG_XML);
    return solverFactory.buildSolver();
}

I assume something is getting iterated while changed at the same time, but the hardest part for me is to figure out how/where exactly, if it's my code, something with xstream while creatingfromxmlresource or something third.

Hope this makes sense to some


EDIT: I learned I should probably have included the warnings

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.thoughtworks.xstream.core.util.Fields (file:/Users/path/my.jar) to field java.util.TreeMap.comparator
WARNING: Please consider reporting this to the maintainers of com.thoughtworks.xstream.core.util.Fields
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

Problem seemed to stem from the computer that got this error was using JDK9, and it usually works fine with JDK8. We downgraded to JDK8 on the given computer, and have since not seen the error.


Solution

  • You're probably modifying the same solverFactory instance from different threads by calling solverFactory.getSolverConfig() (for example to configure the termination time limit dynamically).

    Solution: Look in the docs for SolverFactory.cloneSolverFactory().