Parallel stream doesn't set Thread.contextClassLoader after tomcat upgrade

假装没事ソ 提交于 2019-12-05 07:16:01

Common ForkJoin pool is problematic and could be responsible for memory leaks and for applications being able to load classes and resources from other contexts/applications (potential security leak if your tomcat is multi tenant). See this Tomcat Bugzilla Report.

In Tomcat 8.5.11 they had applied fix to the above issues by introducing SafeForkJoinWorkerThreadFactory.java

In order for your code to work, you can do the following, which will supply explicit ForkJoin and its worker thread factory to the Stream.parallel() execution.

ForkJoinPool forkJoinPool = new ForkJoinPool(NO_OF_WORKERS);
forkJoinPool.execute(() -> warmers.parallelStream().forEach(Warmer::run));

This saved my day! I had to do it like this to make it work:

private static class CustomForkJoinWorkerThread extends ForkJoinWorkerThread {
    CustomForkJoinWorkerThread(ForkJoinPool pool) {
        super(pool);
        setContextClassLoader(Thread.currentThread().getContextClassLoader());
    }
}

private ForkJoinPool createForkJoinPool() {
    return new ForkJoinPool(
            ForkJoinPool.getCommonPoolParallelism(),
            CustomForkJoinWorkerThread::new,
            null,
            false
    );
}


createForkJoinPool().submit(() -> stuff.parallelStream().doStuff())
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!