简体   繁体   中英

How to stop a java application?

I have made a java application and have packed it into an executable jar file. Now a user can start that program from either of the following two ways:

  1. Start if from command prompt by executing the following command on the command prompt:

    java -jar "MyJar.jar"

  2. By double clicking on that jar file.

I want that my client would adopt second approach as it is much easier than the first approach. But the problem with second approach is how to stop application before it has finished?

It is a command-line application.

And no command prompt window appears when a user double clicks on the jar file. So in this case, Will Ctrl + c work?

Stopping (exiting) the application should be inside the application. Whether it is command line or GUI based, the application developer should write code to exit it (For eg., in a command line application you might have something like Press 5 to exit , Press Esc to Exit etc) and in an application with a GUI, you will have to write code to exit when the window is closed, or an EXIT button (or others, depending on your application)

Ctrl + C is KILL the application. This is not a Normal exit. For apps with a GUI, the user would typically (in Windows) go to task manager and end the process (similar ways in other operating systems)

But these are abnormal exits - when the user wants to kill the app when, for instance, the application is no longer responding. Normal exits should be provided by the application (and therefore by the programmer - you)

I've had a similar problem. I have some Java programs that are basically long-running daemon processes. It's nice to be able to stop them and bounce (restart) them.

I've used two approaches. Both have advantages and disadvantages. One is to set up a signal handler, by putting a function like this in some class of your program (in mine, it's in the class with the main method).

import sun.misc.Signal;
import sun.misc.SignalHandler;
...
  private static boolean stopNow = false;
  private static boolean restartNow = false;
...
      private static void handleSignals() {
    try {

        Signal.handle(new Signal("TERM"), new SignalHandler() {
            // Signal handler method for CTRL-C and simple kill command.
            public void handle(Signal signal) {
                MyClass.stopNow = true;
            }
        });
    }
    catch (final IllegalArgumentException e) {
        logger.warn("No SIGTERM handling in this instance.");
    }
    try {
        Signal.handle(new Signal("INT"), new SignalHandler() {
            // Signal handler method for kill -INT command
            public void handle(Signal signal) {
                MyClass.stopNow = true;
            }
        });
    }
    catch (final IllegalArgumentException e) {
        logger.debug("No SIGINT handling in this instance.");
    }
    try {

        Signal.handle(new Signal("HUP"), new SignalHandler() {
            // Signal handler method for kill -HUP command
            public void handle(Signal signal) {
                MyClass.restartNow = true;
            }
        });
    }
    catch (final IllegalArgumentException e) {
        logger.warn("No SIGHUP handling in this instance.");
    }
}

This has worked robustly for us in production. You need a genuine Sun JRE for this to work; the one shipped with a typical Linux distro doesn't have the Signal stuff in it. It works OK on Windows too, but you don't get the HUP signal. You do need a shortcut or shellscript to launch this thing.

Also, keep in mind that signal handling is a big fat botch. Don't try to do very much inside your signal handler. You can see that my sample code simply sets static flags. Other parts of my program detect that the flag changed, and shut down. I could have experimented with more complex code inside the signal handler, but I didn't feel like taking on the QA burden.

The other approach is to structure your program as a Servlet. You'll write a class that extends HttpServlet in this case. Override Servlet.init with a method that starts your worker thread. Likewise, Override Servlet.destroy with a method that shuts yourself down.

Then you can use a Java EE container server like Tomcat to manage your starting and stopping.

If your program is a console mode program and it's doing output, Ctrl-C should be able to kill it.

If it's a GUI program, you'll want to give it a button to exit, or at least setting EXIT_ON_CLOSE as the defaultCloseOperation of your main JFrame.

ctrl+alt+suppr -> kill the javaw.exe ? :p

Or you would have to present a user interface with a stop button (see swing etc)

It depends on the User Interface. If its a Swing application then you can setDefaulCloseOperation(JFrame.EXIT_ON_CLOSE) on your main Frame. If its a console app and the user is interacting with it then you ask the user to enter a value that indicates to you that they want to stop the app. If yoy are not interacting with the user at all then ctrl-c will have to work.

I've used socket connection to enable kill of running instance.

    //send kill signal to running instance, if any
    try {
        new Socket("localhost", 4000).getInputStream().read(); //block until its done
    } catch (Exception e) { //if no one is listening, we're the only instance
    }
    //start kill listener for self
    new Thread() {

        @Override
        public void run() {
            try {
                ServerSocket serverSocket = new ServerSocket(4000);
                serverSocket.accept();

                //do cleanup here

                serverSocket.close();
            } catch (Exception e) {
            }
            System.exit(0);
        }
    }.start();

You can use this one: exit()

It's possible to predefine all the action before virtual machine is totally stoppeed thus you can save your data and performa all actions to prevent the data loss. I'm not sure it's a good way, because I've just started Java study, but it seems working.

Is it a GUI application or commandline.

In first case just handle the window closing event. In second case handle eg CTRL + C

that depends on what kind of application is it?

Is it a swing application? If so, then your app should handle when user clicks the 'close' button. There is a behavior for that. JFrame.close()

If it isnt a swing app then ctrl+c will work.

"It is a command-line application" you say.. Well you could do it so that when the user hit a button (say esc) he can write short commands to exit, restart etc..

You can do this with KeyListener . When ESC is hit (say that is the button you want the user to hit), you use Scanner on System.in, and you will do a System.exit(0); if the input is "exit".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM