source

Java 프로세스를 정상적으로 정지하는 방법

manysource 2022. 11. 24. 21:41

Java 프로세스를 정상적으로 정지하는 방법

Linux 및 Windows에서 Java 프로세스를 정상적으로 중지하려면 어떻게 해야 합니까?

언제?Runtime.getRuntime().addShutdownHook전화받고 언제 안 받죠?

파이널라이저는요? 도움이 되나요?

셸에서 Java 프로세스로 신호를 보낼 수 있습니까?

휴대성이 좋은 솔루션을 찾고 있습니다.

셧다운 후크는 VM이 강제로 중지되지 않은 모든 경우에 실행됩니다.그래서 만약 당신이 "표준" 킬을 발행한다면SIGTERM명령어를 실행한다.마찬가지로 콜 후에 실행됩니다.System.exit(int).

하지만 힘든 살생(kill -9또는kill -SIGKILL실행하지 않습니다.마찬가지로 컴퓨터의 전원을 끄거나, 끓는 용암통에 떨어뜨리거나, CPU를 큰 망치로 두들겨 부수면(그리고 명백하게) 실행되지 않습니다.하지만 당신은 이미 알고 있었을 겁니다.

파이널라이저도 실제로 실행되어야 하지만 셧다운 청소에 의존하지 말고 셧다운 후크에 의존하여 작업을 완전히 중단하는 것이 좋습니다.그리고 항상 그렇듯이 교착 상태에 주의해야 합니다(전체 프로세스에 너무 많은 셧다운 훅이 걸려 있는 것을 보았습니다).

네, 'Java Monitoring and Management'와 협력하기로 선택한 모든 가능성에도 불구하고
개요는 이쪽
이것에 의해, 어느 애플리케이션을 다른 애플리케이션으로부터 비교적 간단하게 제어할 수 있습니다.스크립트에서 제어 애플리케이션을 호출하여 제어된 애플리케이션을 종료하기 전에 정상적으로 중지할 수 있습니다.

다음은 간단한 코드입니다.

제어된 응용 프로그램:
다음 VM 매개 변수를 사용하여 실행합니다.
- DCOM.sun.management.jmxremote
- DCOM.sun.management.jmxremote.포트=9999
- DCOM.sun.management.jmxremote.authenticate=false
- DCOM.sun.management.jmxremote.ssl=false

//ThreadMonitorMBean.java
public interface ThreadMonitorMBean
{
String getName();
void start();
void stop();
boolean isRunning();
}

// ThreadMonitor.java
public class ThreadMonitor implements ThreadMonitorMBean
{
private Thread m_thrd = null;

public ThreadMonitor(Thread thrd)
{
    m_thrd = thrd;
}

@Override
public String getName()
{
    return "JMX Controlled App";
}

@Override
public void start()
{
    // TODO: start application here
    System.out.println("remote start called");
}

@Override
public void stop()
{
    // TODO: stop application here
    System.out.println("remote stop called");

    m_thrd.interrupt();
}

public boolean isRunning()
{
    return Thread.currentThread().isAlive();
}

public static void main(String[] args)
{
    try
    {
        System.out.println("JMX started");

        ThreadMonitorMBean monitor = new ThreadMonitor(Thread.currentThread());

        MBeanServer server = ManagementFactory.getPlatformMBeanServer();

        ObjectName name = new ObjectName("com.example:type=ThreadMonitor");

        server.registerMBean(monitor, name);

        while(!Thread.interrupted())
        {
            // loop until interrupted
            System.out.println(".");
            try 
            {
                Thread.sleep(1000);
            } 
            catch(InterruptedException ex) 
            {
                Thread.currentThread().interrupt();
            }
        }
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        // TODO: some final clean up could be here also
        System.out.println("JMX stopped");
    }
}
}

응용 프로그램 제어:
명령줄 인수로 stop 또는 start를 사용하여 실행합니다.

public class ThreadMonitorConsole
{

public static void main(String[] args)
{
    try
    {   
        // connecting to JMX
        System.out.println("Connect to JMX service.");
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
        JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

        // Construct proxy for the the MBean object
        ObjectName mbeanName = new ObjectName("com.example:type=ThreadMonitor");
        ThreadMonitorMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, ThreadMonitorMBean.class, true);

        System.out.println("Connected to: "+mbeanProxy.getName()+", the app is "+(mbeanProxy.isRunning() ? "" : "not ")+"running");

        // parse command line arguments
        if(args[0].equalsIgnoreCase("start"))
        {
            System.out.println("Invoke \"start\" method");
            mbeanProxy.start();
        }
        else if(args[0].equalsIgnoreCase("stop"))
        {
            System.out.println("Invoke \"stop\" method");
            mbeanProxy.stop();
        }

        // clean up and exit
        jmxc.close();
        System.out.println("Done.");    
    }
    catch(Exception e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}


이상입니다. :-)

다른 방법으로는 응용 프로그램이 서버 socet을 열고 정보가 도착할 때까지 기다릴 수 있습니다.예를 들어, "magic" 워드를 가진 문자열이 셧다운되도록 응답합니다.System.exit().이러한 정보는 telnet 등의 외부 애플리케이션을 사용하여 socke로 전송할 수 있습니다.

조금 까다롭지만 휴대성이 뛰어난 솔루션을 소개합니다.

  • 응용 프로그램에 셧다운 훅 구현
  • JVM을 정상적으로 셧다운하려면 Attach API를 사용하여 System.exit()을 호출하는 Java Agent를 설치합니다.

자바 에이전트를 구현했습니다.Github: https://github.com/everit-org/javaagent-shutdown 에서 구할 수 있습니다.

솔루션의 상세한 것에 대하여는, https://everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process/ 를 참조해 주세요.

여기서도 같은 질문입니다.

Java의 피니셔는 불량입니다.쓰레기 수거에 많은 오버헤드를 더합니다.가능하면 피하세요.

셧다운후크는 VM이 종료될 때만 호출됩니다.당신이 원하는 대로 잘 할 수 있을 것 같아요.

Linux 에서의 시그널링은 "kill"(사용 가능한 신호에 대한 man kill)로 실행할 수 있습니다.그렇게 하려면 프로세스 ID(ps ax | grep java) 등이 필요합니다.프로세스가 작성되었을 때 프로세스 ID를 저장합니다(대부분의 Linux 스타트업 파일에 사용됩니다./etc/initd 참조).

휴대용 시그널링은 Java 응용 프로그램에 SocketServer를 통합함으로써 실행할 수 있습니다.그렇게 어렵지 않고 원하는 명령어를 자유롭게 보낼 수 있습니다.

finalizer가 아닌 finalizer를 의미하는 경우 System.exit()가 호출될 때 구가 extecut되지 않습니다.파이널라이저는 동작하지만 디버깅스테이트먼트를 인쇄하는 것 이외에는 의미가 없습니다.그들은 위험합니다.

답변 감사합니다.셧다운 훅이 제 경우처럼 이음새에 잘 맞습니다.그런데 '모니터링과 관리 콩'이라는 것도 우연히 만났어요.
http://java.sun.com/j2se/1.5.0/docs/guide/management/overview.htmlhttpjava.sun.com/j2se/1.5.0/docs/guide//overview.html
및 프로세스의 몇 가지 수 5Java는 Java 프로세스를 조작할 수 있습니다.

언급URL : https://stackoverflow.com/questions/191215/how-to-stop-java-process-gracefully