Java ExecutorService
Recently, I was working on HDFS-17030 and used ExecutorService for multi-threading execution. We hit a non-intuitive `bug` of how JVM/garbage collector works. The issue is as following.
We created an executorService with 1 core thread in a class. We did not set allowCoreThreadTimeOut to true (default is false). So, that core thread will be kept running, even when the main thread exits! Then, the JVM process won’t exit, because there is still one thread running! Even when we shut down the executorService in .close() method of that class, the same issue persists. The issue is .close() method of a Closable object is called by Java garbage collector only when it is reclaiming that object. This does not happen immediately when there is no reference to an object. After an object becomes orphan (no more reference to it), it will be added to a queue. The garbage collector will look into the queue and determine which objects to reclaim based on its own algorithm. It is undeterministic/out of control from programmers on when the garbage collector will reclaim an object.
The following code is an example.
|
|
- When we comment out line 17
pool.allowCoreThreadTimeOut(true);
, the core thread will be kept running and the JVM process kept running, though the main thread exits.
|
|
Intellij threaddump showed there is a thread “myThread-1” in parking
state,
waiting for new tasks to execute.
- After we comment out
pool.allowCoreThreadTimeOut(true);
, the core thread will be running idle for 10 seconds before terminating. After that, the JVM process also exited. Please note theProcess finished with exit code 0
message at the end.
|
|
At first glance, this looks a bit wired, as when the main thread exits, we would expect the program to shut down. In retrospect, the main thread is just one of the threads in a JVM process. So, as long as there is one runnable/running thread, the JVM process won’t shut down itself.
Output from .close() is not redirected as part of stdout. They don’t show up in the output.