Describe the bug
A severe "nested concurrency" leak exists in com.alibaba.datax.plugin.rdbms.util.DBUtil. The class defines a ThreadLocal<ExecutorService> named rsExecutors that initializes a new FixedThreadPool(1) for every calling thread. However, there is no mechanism to clean this up: ExecutorService.shutdown() and rsExecutors.remove() are never invoked.
Impact
Because DataX is a highly concurrent data synchronization framework, multiple task threads will access DBUtil. Each of these worker threads will secretly spawn its own dedicated underlying thread pool that lives forever.
This causes an exponential explosion of underlying OS threads. Eventually, this exhausts the operating system's ulimit thread limit, directly crashing the JVM with a java.lang.OutOfMemoryError: unable to create new native thread.
Suggested Fix
The use of ThreadLocal to cache thread pools is an anti-pattern here.
Remove the ThreadLocal wrapper entirely. Declare a single, globally shared static ExecutorService (e.g., a cached thread pool with a proper timeout and rejection policy) for all asyncResultSetNext calls to reuse. This will immediately resolve the thread explosion issue.
Describe the bug
A severe "nested concurrency" leak exists in
com.alibaba.datax.plugin.rdbms.util.DBUtil. The class defines aThreadLocal<ExecutorService>namedrsExecutorsthat initializes a newFixedThreadPool(1)for every calling thread. However, there is no mechanism to clean this up:ExecutorService.shutdown()andrsExecutors.remove()are never invoked.Impact
Because DataX is a highly concurrent data synchronization framework, multiple task threads will access
DBUtil. Each of these worker threads will secretly spawn its own dedicated underlying thread pool that lives forever.This causes an exponential explosion of underlying OS threads. Eventually, this exhausts the operating system's
ulimitthread limit, directly crashing the JVM with ajava.lang.OutOfMemoryError: unable to create new native thread.Suggested Fix
The use of
ThreadLocalto cache thread pools is an anti-pattern here.Remove the
ThreadLocalwrapper entirely. Declare a single, globally sharedstatic ExecutorService(e.g., a cached thread pool with a proper timeout and rejection policy) for allasyncResultSetNextcalls to reuse. This will immediately resolve the thread explosion issue.