[ https://issues.apache.org/jira/browse/SIS-193?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Martin Desruisseaux updated SIS-193: ------------------------------------ Fix Version/s: (was: 1.1) 1.2 Affects Version/s: 1.1 1.0 > 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 > Affects Versions: 0.6, 0.7, 0.8, 1.0, 1.1 > Reporter: Martin Desruisseaux > Assignee: Martin Desruisseaux > Priority: Minor > Labels: JDK9 > Fix For: 1.2 > > > 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 (v8.3.4#803005)