Details
-
Task
-
Status: Closed
-
Minor
-
Resolution: Fixed
-
0.6, 0.7, 0.8, 1.0, 1.1, 1.2, 1.3
Description
As of 1.8.0_31-b13, java.util.ServiceLoader does not support usage of a second Iterator in the middle of a previous iteration. The following Java code provides two simple tests with a ServiceLoader iterating over two elements.
import java.util.Iterator; import java.util.ServiceLoader; public class ServiceLoaderTest { public static class I1 extends ServiceLoaderTest {} // A dummy provider. public static class I2 extends ServiceLoaderTest {} // An other provider. public static void main(String[] args) { test1(); test2(); } private static void test1() { System.out.println(); System.out.println("---- TEST 1 ----"); ServiceLoader<ServiceLoaderTest> loader = ServiceLoader.load(ServiceLoaderTest.class); Iterator<ServiceLoaderTest> it1 = loader.iterator(); System.out.println("it1.hasNext() = " + it1.hasNext()); System.out.println("it1.next() = " + it1.next()); Iterator<ServiceLoaderTest> it2 = loader.iterator(); System.out.println("it2.hasNext() = " + it2.hasNext()); System.out.println("it2.next() = " + it2.next()); System.out.println("it1.hasNext() = " + it1.hasNext()); System.out.println("it1.next() = " + it1.next()); System.out.println("it2.hasNext() = " + it2.hasNext()); // Expected "true" here, but get "false". } private static void test2() { System.out.println(); System.out.println("---- TEST 2 ----"); ServiceLoader<ServiceLoaderTest> loader = ServiceLoader.load(ServiceLoaderTest.class); Iterator<ServiceLoaderTest> it1 = loader.iterator(); System.out.println("it1.hasNext() = " + it1.hasNext()); System.out.println("it1.next() = " + it1.next()); Iterator<ServiceLoaderTest> it2 = loader.iterator(); System.out.println("it1.hasNext() = " + it1.hasNext()); System.out.println("it2.hasNext() = " + it2.hasNext()); System.out.println("it1.next() = " + it1.next()); System.out.println("it2.next() = " + it2.next()); // ConcurrentModificationException here. } }
The second test throws the following exception:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:711) at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:744) at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:742) at java.util.ServiceLoader$1.next(ServiceLoader.java:479) at test.ServiceLoaderTest.test2(ServiceLoaderTest.java:47) at test.ServiceLoaderTest.main(ServiceLoaderTest.java:12)
The workaround applied in Apache SIS has been to add a LazySet internal class which wraps an Iterable and caches its values. But this is a little bit unfortunate since ServiceLoader already caches its values.
ServiceLoader is probably going to be significantly rewritten in JDK9 as a side effect of the Jigsaw project. So we should revisit if our LazySet workaround is still needed on a JDK9 branch.
Attachments
Issue Links
- depends upon
-
SIS-561 Upgrade to Java 11
- Closed