ConcurrentModificationException in java.util.ServiceLoader (not a multi-thread issue)

Martin Desruisseaux martin.desruisseaux at geomatys.fr
Mon Feb 23 18:05:55 UTC 2015


Apparently the test case that I attached to my previous email was list.
There is a copy-and-paste of the 2 tests reproducing the ServiceLoader
issue:

package test;

import java.util.Iterator;
import java.util.ServiceLoader;

public class ServiceLoaderTest {
    public static class I1 extends ServiceLoaderTest {}
    public static class I2 extends ServiceLoaderTest {}

    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.
    }
}



Martin


Le 23/02/15 15:20, Martin Desruisseaux a écrit :
> Hello all
>
> java.util.ServiceLoader does not seem to support usage of a second
> Iterator in the middle of a previous iteration. The attached Java file
> provides two simple tests with a ServiceLoader iterating over two
> elements. The first test creates two iterators and invokes their
> hasNext() / next() methods in the following order:
>
>   * Iterator 1
>   * Iterator 2
>   * Iterator 1
>   * Iterator 2  -  unexpected end of iteration here.
>
> The second test creates two iterators and invoke the hasNext() methods
> on both iterators before to invoke their next() methods. This result is
> the following exception (tested on 1.8.0_31-b13):
>
>     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)
>
> (note: to run the test, the attached test.ServiceLoaderTest file needs
> to be in the META-INF/services/ directory). I found a Stackoverflow
> thread mentioning this issue 4 years ago [1], but apparently without
> solution. Should I look for a patch, or is the current behaviour
> considered okay (in which case I would suggest to warn the users in the
> Javadoc)?
>
>
>     Martin
>
>
> [1] http://stackoverflow.com/questions/2593777/serviceloader-double-iterator-issues
>
>




More information about the core-libs-dev mailing list