我在春季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)