【Java】CompletableFuture.orTimeout在JDK21以下版本有内存泄漏及解决方案
本文介绍CompletableFuture#orTimeout这个API在JDK-21版本以下的导致内存泄漏的bug,并提供两种解决方案。
JDK bug issue链接: https://bugs.openjdk.org/browse/JDK-8303742
这个BUG是在JDK-21中被修复的,也就是说如果你使用的JDK低于21,那么orTimeout这个API是有内存泄漏风险的。
问题描述
CompletableFuture.orTimeout会调度一个延迟任务,用于在超时到期前future还未complete的情况下,通过一个TimeoutException异常来exceptionally complete(API接口)来完成future任务。如果future对象在超时之前完成,则延迟任务将被取消并从延迟的执行器队列中删除。
JDK的这个bug是,只有在future对象non-exceptionally complete时才会发生这种情况,当completed exceptionally时,延迟任务不会被取消,因此其内存会被保留到超时,即使它不再有任何用途。鉴于超时时间应明显长于预期的完成时间,如果经常发生异常完成,这种泄漏是不可忽视的。
问题的根因发生在下面这个代码片段,在源码的CompletableFuture.Canceller.accept里。