leventov/Koloboke

new map creation in multiple threads throws java.util.NoSuchElementException

amirkamran opened this issue · 10 comments

Exception in thread "pool-1-thread-1" java.util.NoSuchElementException
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:340)
at java.util.ServiceLoader$1.next(ServiceLoader.java:428)
at net.openhft.koloboke.collect.map.hash.HashIntDoubleMaps.getDefaultFactory(HashIntDoubleMaps.java:56)
at net.openhft.koloboke.collect.map.hash.HashIntDoubleMaps.newMutableMap(HashIntDoubleMaps.java:81)
at Test.run(Test.java:18)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:695)

Please try to synchronize map creation externally, for example, extract a static synchronized method which creates IntDoubleMaps. If problem disappears, I will synchronize HashIntDoubleMaps.getDefaultFactory() method.

Yes, that solves the issue.

I'll publish version with a fix tomorrow -- please check then.

@leventov thanks .. it works !

I have 0.6.6 and still get this error, both in the java 7 and java 8 versions. Specifically, I have a function: private static synchronized HashCharCharMapFactory getHashCharCharMapFactory() {
return HashCharCharMaps.getDefaultFactory();
}
that when called gives the following exception: Exception in thread "main" java.lang.ExceptionInInitializerError
at net.openhft.koloboke.collect.map.hash.HashCharCharMaps.getDefaultFactory(HashCharCharMaps.java:52)
at KolobokeVsFastUtilDemo.getHashCharCharMapFactory(KolobokeVsFastUtilDemo.java:65)
at KolobokeVsFastUtilDemo.main(KolobokeVsFastUtilDemo.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

@athawk81 please check you have -impl JAR in the classpath.

@leventov I am still seeing this issue (or one similar to it) when using version 0.6.8 with Java 8:

java.lang.ExceptionInInitializerError
    at net.openhft.koloboke.collect.set.hash.HashIntSets.getDefaultFactory(HashIntSets.java:49)
    at net.openhft.koloboke.collect.set.hash.HashIntSets.newMutableSet(HashIntSets.java:68)
    at com.test.benchmark.KolobokeCollectionsBenchmark.getSet(KolobokeCollectionsBenchmark.java:48)
    at com.test.benchmark.KolobokeCollectionsBenchmark.kolobokieSetBenchmark(KolobokeCollectionsBenchmark.java:34)
    at com.test.benchmark.generated.KolobokeCollectionsBenchmark_kolobokieSetBenchmark_jmhTest.kolobokieSetBenchmark_thrpt_jmhStub(KolobokeCollectionsBenchmark_kolobokieSetBenchmark_jmhTest.java:104)
    at com.test.benchmark.generated.KolobokeCollectionsBenchmark_kolobokieSetBenchmark_jmhTest.kolobokieSetBenchmark_Throughput(KolobokeCollectionsBenchmark_kolobokieSetBenchmark_jmhTest.java:69)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:430)
    at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:412)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.util.NoSuchElementException
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:365)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
    at net.openhft.koloboke.collect.set.hash.HashIntSets$DefaultFactoryHolder.<clinit>(HashIntSets.java:36)
    ... 16 more

I have followed the advice in this thread to create the set (or map -- seeing the same issue when using the factory for map creation) in a static, synchronized method, but no luck. Please let me know if I should open another issue or if you need any additional information.

@jdpgrailsdev the synchronization issue has been solved -- you shouldn't create a Set in a synchronized block.

Please check that you have both -api and -impl jars in the classpath, e. g. using Maven:

<dependencies>
    <dependency>
        <groupId>net.openhft</groupId>
        <artifactId>koloboke-api-jdk8</artifactId>
        <version>0.6.8</version>
    </dependency>
    <dependency>
        <groupId>net.openhft</groupId>
        <artifactId>koloboke-impl-jdk8</artifactId>
        <version>0.6.8</version>
    </dependency>
<dependencies>

@leventov
I can confirm that I have both on the classpath (using Gradle):

ext {
    kolobokeVersion = '0.6.8'
}

dependencies {
    compile "net.openhft:koloboke-api-jdk8:${kolobokeVersion}"
    runtime "net.openhft:koloboke-impl-jdk8:${kolobokeVersion}"
}

I tried going back to creating the map/set in a non-synchronized fashion, but I still get the same error:

java.lang.ExceptionInInitializerError
    at net.openhft.koloboke.collect.map.hash.HashIntIntMaps.getDefaultFactory(HashIntIntMaps.java:52)
    at net.openhft.koloboke.collect.map.hash.HashIntIntMaps.newMutableMap(HashIntIntMaps.java:76)
    at com.test.benchmark.KolobokeCollectionsBenchmark.getMap(KolobokeCollectionsBenchmark.java:41)
    at com.test.benchmark.KolobokeCollectionsBenchmark.kolobokeMapBenchmark(KolobokeCollectionsBenchmark.java:26)
    at com.test.benchmark.generated.KolobokeCollectionsBenchmark_kolobokeMapBenchmark_jmhTest.kolobokeMapBenchmark_thrpt_jmhStub(KolobokeCollectionsBenchmark_kolobokeMapBenchmark_jmhTest.java:104)
    at com.test.benchmark.generated.KolobokeCollectionsBenchmark_kolobokeMapBenchmark_jmhTest.kolobokeMapBenchmark_Throughput(KolobokeCollectionsBenchmark_kolobokeMapBenchmark_jmhTest.java:69)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:430)
    at org.openjdk.jmh.runner.BenchmarkHandler$BenchmarkTask.call(BenchmarkHandler.java:412)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.util.NoSuchElementException
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:365)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
    at net.openhft.koloboke.collect.map.hash.HashIntIntMaps$DefaultFactoryHolder.<clinit>(HashIntIntMaps.java:37)
    ... 16 more

Here is an example of how I am creating the map:

private Map<Integer, Integer> map = null;

...

public void someMethod(final Integer key) {
     if(getMap().containsKey(key)) {
         ...
    }
}

private Map<Integer,Integer> getMap() {
    if(map == null) {
        map = HashIntIntMaps.newMutableMap();
    }
    return map;
}

Previously, the getMap method was a static, synchronized method, but that too produced the same error.