TL;DR: Is there a way to find out, that JVM-shutdown is only prevented from the threads started by my code? Is it for example possible to automatically trigger AutoCloseable.close() on Shutdown?
I am building a library, that should be used by several customers. This means, besides providing a documentation, I can't enforce certain things.
(I try to describe it as abstract as possible and avoid unnecessary details)
I have a "Manager" object (which is kind of a Factory), that is used to create a "Service" object, that in turn needs some data to work accordingly. Since that data is loaded from some "slow" backend service (which also might change from time to time), I use a separate (Daemon)-Thread that checks for updates and injects new data into that service as soon as available. (This also means that unless the first update, that service is simply in "noop mode". But that's ok.)
Now the "Updater" (which runs in my daemon thread) uses a library that again starts a thread when opening a connection and it's necessary to call "close" to ensure that this secondary thread is stopped - otherwise it is not possible, to shutdown the JVM properly.
As a safety-net I call the close() method inside the finalize() method of my "Manager" (which keeps a reference to all Updater instances). This is not 100% safe, since it's not predictable when GC runs (even more during shutdown!), but it's my only option.
Update: Here is some abstract example code that illustrates the architecture and the according problem
This architecture causes two possible pitfalls:
If the implementation does not keep a reference to the instance of the manager, it will be garbage collected at some point and trough the finalize method the necessary background updates will be stopped.
If the implementation keeps an instances of the manager, it must call the close method during the shutdown of the according system, otherwise the JVM can't terminate properly.
So my actual problem is the "potential unreliability" of the developers, which are using that library.
Does anyone have an idea how to build a solution, that could handle both pitfalls? It would be nice to have some Auto-AutoCloseable ;) that is called during Shutdown (e.g by the DestroyJavaVM Thread or similar).
Inside the Updater I am closing the "problematic" connection inside a "try-finally" block, but that daemon thread is not interrupted / stopped automatically as well.
I registered a Runtime.getRuntime().addShutdownHook(...)
that would close all connections, but this shutdown hook is never called since a Shutdown is only initiated when all user-threads are stopped.
I solved my problem as I found that the third party library (RabbitMQ Client) offers a setThreadFactory
method that I can use to ensure the spawned Threads are Daemon-Threads.
Good luck for me with my 3rd party library, but the described problem is still possible.
You want the AutoCloseable resources to be closed so the shutdown is orderly, I guess.
AutoCloseable objects should be used (by your library clients) in a manner that ensures they are closed when they are no longer needed. In almost all cases, they should be using a try-with-resources block, so they are closed even if an exception is thrown.
You should take advantage of that by requiring your library clients perform a controlled shutdown of each thread when they receive a request to shutdown the program. A thread performs a controlled shutdown by returning from each Runnable.run method, or throwing an exception from each Runnable.run method. I believe this is the only reliable means of closing resources, because it ensures nested resource allocations are reallocated in the correct order. More generally, as a library writer you can not know what other operations your library clients might want to do on shutdown, so you should give them complete control over the shutdown.
You can help them do that by having your library code properly handle InterruptedException and the Thread.interrupted flag.