Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a Java program detect that the MacOS machine is being shut down?

Tags:

java

macos

daemon

I have a Java application that I want to be started on my Mac whenever I start the machine. The application should be shut down gracefully whenever the machine is shut down.

I added a shutdown hook in the main method:

Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook(scheduler)));

ShutdownHook class looks like this:

public class ShutdownHook implements  Runnable {
    private final static Logger LOGGER = LoggerFactory.getLogger("Shutdown Hook");
    private final Scheduler scheduler;

    public ShutdownHook(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    @Override
    public void run() {
        LOGGER.debug("Starting to shot down the application");
        try {
            scheduler.shutdown();
        } catch (final SchedulerException e) {
           LOGGER.error("An error occurred while trying to shut down the scheduler", e);
        }
        LOGGER.info("Exiting the shutdown hook");
    }
}

Then I built the application into an executable JAR and added it to the list of "Login items".

"Users and Groups" window

The application is started when I log in.

However, the shutdown hook is not executed when the machine shuts down.

How can I make sure that when I shut down the machine using the menu item shown below, a running Java application detects that the machine is shutting down?

"Shutdown" menu item

Update 1:

As far as I understand, one way to fix the error is to use launchd to start the Java program. I wrote the plist file below.

The next question is how to make sure that launchd runs the application described in that plist file?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ExitTimeOut</key>
    <integer>300</integer>
    <key>StandardErrorPath</key>
    <string>/Users/XXXXXX/sw/wordcounter-daemon/error</string>
    <key>Label</key>
    <string>com.dpisarenko.wordcounterdaemon</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/java</string>
        <string>-jar</string>
        <string>/Users/XXXXXXX/sw/wordcounter-daemon/wordcounter-daemon-0.1-jar-with-dependencies.jar</string>
    </array>
</dict>
</plist>
like image 605
Dmitrii Pisarenko Avatar asked Jul 18 '21 14:07

Dmitrii Pisarenko


People also ask

How do you shutdown a system in Java?

To shutdown computer in Java programming, you have to use the command shutdown -s. You can also specify the time in seconds, after which you want to turn off or shutdown the PC, using shutdown -s -t seconds. Where seconds refers to the number of seconds. Note - To shutdown the computer, use shutdown -s.

How to shut down running JVM processes?

There are two ways to terminate the JVM instance from the running application: Calling the exit() method, which initiates the JVM normal shutdown sequence: run all registered shutdown hooks; run all uninvoked finalizers; then end the JVM instance. Calling the halt() method, which ends the JVM instance immediately.

How to stop JVM from command line?

Use the -stop command to stop the JVM controller. You must supply the name of the JVM controller as an argument for the JVM controller you want to stop. You will receive an error if a JVM controller with the specified name is not running. There is no additional option.


Video Answer


1 Answers

Usually Unix-style systems will shutdown a daemon process in two steps:

  1. SIGTERM signal send to process

  2. SIGKILL signal send to process if the process still runs after X seconds after point 1

This answer explains how to configure ExitTimeOut value which controlls time between these two signals on MacOS.

The behaviour for non-daemon processes might be different and this might be the reason your process is not executing JVM shutdown hook. The JVM probably received SIGKILL and by design a user-space process can't handle this signal. Potentially you want to convert your process to a daemon.

like image 180
Karol Dowbecki Avatar answered Oct 19 '22 21:10

Karol Dowbecki