Details

    • Type: Task
    • Status: Open
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: 0.6, 0.7, 0.8
    • Fix Version/s: 1.0
    • Component/s: Referencing
    • Labels:

      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

            Activity

              People

              • Assignee:
                desruisseaux Martin Desruisseaux
                Reporter:
                desruisseaux Martin Desruisseaux
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated: