Shutdown hooks can be useful, but should not be overused, as they are a bit arcane and non-obvious.
People often use shutdown hooks to get something done after some random piece of code does System.exit(). However, it is often better to avoid using System.exit() altogether, or at least to restrict its use to a single place in the whole application.
System.exit() is a generally evil thing to do, in anything except a throw-away piece of utility code. It kills the whole JVM process, regardless of what other threads may be doing, and it is rare that you really know what other threads are doing, and hence whether it is actually appropriate to kill the JVM.
Much better to organise all your threads to terminate cleanly, when they have done their work, or when they receive some application-wide shutdown signal. If you organise your application like this, you can likely code shutdown procedures in ordinary
Java code, rather than needing nasty shutdown hooks.