2009-11-07 4 views
4

java 응용 프로그램을 만들고 실행 가능한 jar 파일로 압축했습니다. 이제 사용자는 다음과 같은 두 가지 방법 중 하나에서 해당 프로그램을 시작할 수 있습니다자바 애플리케이션을 중지하는 방법은 무엇입니까?

자바 -jar "MyJar.jar"

:

  1. 시작 명령 프롬프트에서 명령 프롬프트에서 다음 명령을 실행했을 경우

  2. 해당 jar 파일을 두 번 클릭하십시오.

가 나는 첫 번째 방법보다 훨씬 쉽게 나의 클라이언트가 두 번째 접근 방식을 채택 할 것이라고합니다. 그러나 두 번째 접근법의 문제점은 응용 프로그램이 끝나기 전에 응용 프로그램을 중지하는 방법입니다.

명령 줄 응용 프로그램입니다.

사용자가 jar 파일을 두 번 클릭해도 명령 프롬프트 창이 표시되지 않습니다. 그래서이 경우에 Ctrl + c가 작동합니까?

답변

9

응용 프로그램을 중지 (종료)하는 것은 응용 프로그램 내부에 있어야합니다. 명령 행이든 GUI 기반이든 관계없이 응용 프로그램 개발자는 종료 할 코드를 작성해야합니다 (예 :명령 줄 응용 프로그램에서 Press 5 to exit, Press Esc to Exit 등) 및 GUI가있는 응용 프로그램에서 창을 닫을 때 종료 코드를 작성하거나 EXIT 단추 (또는 응용 프로그램에 따라 다른 코드)를 작성해야합니다)

Ctrl + C은 KILL 응용 프로그램입니다. 이것은 이 아니고 정상 종료입니다. GUI가있는 앱의 경우 일반적으로 사용자가 작업 관리자로 이동하여 프로세스를 종료합니다 (다른 운영체제에서와 유사한 방식)

하지만 비정상적인 종료 - 사용자가 앱을 죽일 때, 예를 들어, 응용 프로그램이 더 이상 응답하지 않습니다. 정상적인 종료는 응용 프로그램에서 제공해야합니다 (따라서 프로그래머 - 사용자가)

2

프로그램이 콘솔 모드 프로그램이고 출력을 수행 중이면 Ctrl-C가이를 종료 할 수 있어야합니다.

GUI 프로그램 인 경우 종료 버튼을 지정하거나 적어도 EXIT_ON_CLOSE을 기본 JFrame의 defaultCloseOperation으로 설정해야합니다.

1

ctrl + alt + suppr -> javaw.exe를 죽입니까? : P

아니면 정지 버튼이있는 사용자 인터페이스를 제공 할 것입니다 (등 스윙 참조)

1

은 사용자 인터페이스에 따라 달라집니다. Swing 어플리케이션의 경우, 메인 프레임의 SetDefaulCloseOperation (JFrame.EXIT_ON_CLOSE)을 실행할 수 있습니다. 콘솔 앱과 사용자가 앱과 상호 작용하는 경우 사용자에게 앱 중지를 알리는 값을 입력하도록 요청합니다. yoy가 사용자와 전혀 상호 작용하지 않으면 ctrl-c가 작동해야합니다.

0

GUI 응용 프로그램이나 명령 줄입니까?

첫 번째 경우에는 창 닫기 이벤트 만 처리하면됩니다. 두 번째 경우, 예를 들어. Ctrl + C

0

어떤 종류의 응용 프로그램입니까?

스윙 어플 리케이션입니까? 그렇다면 앱이 사용자가 '닫기'버튼을 클릭 할 때 처리해야합니다. 그것에 대한 행동이 있습니다. JFrame.close()

스윙 앱이 아닌 경우 Ctrl + C가 작동합니다.

+0

JFrame.close()는 설정하지 않으면 프로그램을 종료하지 않습니다. 기본 비헤이비어는 프레임을 숨기는 것입니다. 창 닫기 이벤트를 처리하거나 창을 닫을 때 종료하도록 기본 동작을 설정할 수 있습니다. –

0

는 .. 사용자가 버튼을 명중 할 때 (예를 들어 ESC) 그가 등을 다시 시작, 종료 짧은 명령을 쓸 수 있도록 잘 당신이 그것을 할 수 있습니다 .. 당신이 말하는 "그것은 명령 줄 응용 프로그램입니다"

KeyListener으로이 작업을 수행 할 수 있습니다. ESC가 눌려지면 (예를 들어, 사용자가 원하는 버튼), System.in에서 Scanner를 사용하면 System.exit (0); 입력이 "exit"인 경우.

5

비슷한 문제가있었습니다. 기본적으로 장황한 데몬 프로세스 인 Java 프로그램이 있습니다. 그것들을 멈추고 바운스 (다시 시작) 할 수있는 것이 좋다.

저는 두 가지 방법을 사용했습니다. 둘 다 장점과 단점이 있습니다. 하나는 신호 처리기를 설정하는 것입니다.이 함수는 프로그램의 일부 클래스에 있습니다 (예를 들어 main 메서드를 사용하는 클래스에 있습니다).

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."); 
    } 
} 

이것은 제작 과정에서 튼튼하게 작동했습니다. 이 작업을 위해서는 정품 Sun JRE가 필요합니다. 일반적인 리눅스 배포판과 함께 제공되는 패키지에는 Signal 항목이 없습니다. 그것은 Windows에서도 잘 작동하지만 HUP 신호를 얻지는 못합니다. 이 작업을 시작하려면 바로 가기 나 셸 스크립트가 필요합니다.

또한 신호 처리가 큰 뚱뚱한 일이라는 것을 명심하십시오. 신호 처리기 내부에서 많은 작업을하지 마십시오. 내 샘플 코드는 단순히 정적 플래그를 설정한다는 것을 알 수 있습니다. 내 프로그램의 다른 부분은 플래그가 변경된 것을 감지하고 종료합니다. 나는 신호 처리기 내부에서 좀 더 복잡한 코드를 실험 해 볼 수 있었지만 QA 부담을 느끼는 것 같지 않았습니다.

다른 접근법은 프로그램을 서블릿으로 구조화하는 것입니다. 이 경우 HttpServlet을 확장하는 클래스를 작성합니다. worker 스레드를 시작하는 메소드로 Servlet.init를 재정의하십시오. 마찬가지로 Servlet.destroy를 스스로 종료하는 메서드로 재정의하십시오.

그런 다음 Tomcat과 같은 Java EE 컨테이너 서버를 사용하여 시작 및 중지를 관리 할 수 ​​있습니다.

+0

이것은 정확히 내가 찾고 있었던 것이었다. 데몬 프로세스의 경우 제어 된 방식으로 서비스를 중지 할 수 있어야합니다. 이것이 왜 다른 JRE에서 작동하지 않습니까? 신호가 표준 라이브러리의 일부로 정의되지 않는 이유는 무엇입니까? –

0

실행중인 인스턴스를 강제 종료 할 수 있도록 소켓 연결을 사용했습니다.

//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(); 
0

이 하나를 사용할 수 있습니다 : 가상 머신이 완전히 따라서 stoppeed 당신이 데이터 손실을 방지하기 위해 모든 작업 데이터와 퍼포을 저장하기 전에 exit()

그것은 모든 액션을 미리 정의 할 수 있습니다. 방금 ​​Java 연구를 시작했기 때문에 좋은 방법이라고 생각하지 않지만 작동하는 것 같습니다.

관련 문제