简体   繁体   English

并行流在tomcat升级后不设置Thread.contextClassLoader

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

After tomcat upgrade from 8.5.6 to 8.5.28 parallel stream stopped supplying Threads with contextClassLoader: 在tomcat从8.5.6升级到8.5.28后,并行流停止为contexts提供contextClassLoader:

Because of it Warmer::run can't load classes in it. 因为它Warmer::run无法在其中加载类。

warmers.parallelStream().forEach(Warmer::run);

Do you have any ideas what Tomcat was supplying for contextClassLoaders for new Threads? 你有什么想法Tomcat为新线程提供contextClassLoaders的东西吗?

ParallelStream uses ForkJoinPool in newest Tomcat. ParallelStream在最新的Tomcat中使用ForkJoinPool。

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). 常见的ForkJoin池存在问题,可能导致内存泄漏以及能够从其他上下文/应用程序加载类和资源的应用程序(如果您的tomcat是多租户,则可能发生安全漏洞)。 See this Tomcat Bugzilla Report . 请参阅此Tomcat Bugzilla报告

In Tomcat 8.5.11 they had applied fix to the above issues by introducing SafeForkJoinWorkerThreadFactory.java Tomcat 8.5.11中,他们通过引入SafeForkJoinWorkerThreadFactory.java对上述问题进行了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. 为了使代码能够工作,您可以执行以下操作,这将为Stream.parallel()执行提供显式ForkJoin及其工作线程工厂

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())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM