Martin Desruisseaux created SIS-193:
---------------------------------------
Summary: Remove the workaround for ServiceLoader bug
Key: SIS-193
URL: https://issues.apache.org/jira/browse/SIS-193
Project: Spatial Information Systems
Issue Type: Task
Components: Referencing
Reporter: Martin Desruisseaux
Priority: Minor
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.
{code:java}
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.
}
}
{code}
The second test throws the following exception:
{noformat}
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)
{noformat}
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.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)