从并行流收集时,NPE

时间:2019-10-25 17:38:54

标签: java spring hibernate parallel-processing java-stream

我在春季Page中平均包装了约40,000个对象的列表(最多可达到80K)

Page<People> people = //loaded data using PeopleRepository of "People" entity

然后生成地图以将记录导出到excel文件中

List<Map<String, String>> excelData = Streams.batches(people, 500)
            .parallel()
            .map(PageImple::new) //Converting each chunk in a page
            .map(this::buildDTO) // Creating DTO objects from people entities
            .map(Slice::getContent)
            .flatMap(Collection::stream)
            .map(this::buildExportData)
            .collect(                    <----
                Collectors.toList()
             );

上面的代码偶尔会引发以下NPE。它是从核心Java库抛出的。任何人都可以提供任何提示可能是什么原因导致了此问题?它与视差流有关吗?是否需要其他机制进行并行流传输?

例外

    java.lang.NullPointerException: null
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(DelegatingAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:598)
        at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
        at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:735)
        at java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:714)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

在另一种相似的情况下,我也观察到以下异常,

    org.hiberate.AssertionFailure: bug adding collection twice
        at org.hibernate.engine.internal.StatefulPersistenceContext.addCollection(StatefulPersistenceContext.java:851)
        at org.hibernate.engine.internal.StatefulPersistenceContext.addInitializedConnection(StatefulPersistenceContext.java:890)
         // -- Will add remaiing part of the stack trace if required.

编辑2(最新消息!) 我们在两个地方发现了相同的行为。它们都有一条共同的路线,即通过使用惰性获取来加载关系。实体confir如下所示,

@ManyToMany(fetch=Fetch.Lazy)
@JoinTable(.. ... ...)
private Set<Classification> classifications

使用并行流和惰性获取有什么问题吗?

编辑1 经过更多调查后,如果我查看java.util.concurrent.ForkJointTask line#291,则代码如下所示,

try {
    completed = exec();
} catch(Throwable rex) {
    return setExceptionalCompletion(rex);
}

看起来这意味着它未能执行其中一个map块。因此,正如@Eugene在评论中询问它是否是唯一的堆栈跟踪,答案是否定的。有一个“原因” 部分。来了

    Caused By: java.lang.NullPointerException: null
        at org.hibernate.engine.loading.internal.LoadContexts.cleanup(LoadContexts.java:81)
        at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:202)
        at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154)
        at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249)
        at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:212)
        at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:123)
        at org.hibernate.loader.plan.exec.process.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
        at org.hibernate.loader.plan.exec.process.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
        ...
        at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:2004)
        ...
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
        at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

0 个答案:

没有答案