Linux 및 Windows에서 Java 프로세스를 정상적으로 중지하려면 어떻게합니까?
언제 Runtime.getRuntime().addShutdownHook
전화를 받고 언제 전화를받지 않습니까?
파이널 라이저는 어떻습니까? 여기서 도움이됩니까?
쉘에서 Java 프로세스로 일종의 신호를 보낼 수 있습니까?
선호하는 휴대용 솔루션을 찾고 있습니다.
Linux 및 Windows에서 Java 프로세스를 정상적으로 중지하려면 어떻게합니까?
언제 Runtime.getRuntime().addShutdownHook
전화를 받고 언제 전화를받지 않습니까?
파이널 라이저는 어떻습니까? 여기서 도움이됩니까?
쉘에서 Java 프로세스로 일종의 신호를 보낼 수 있습니까?
선호하는 휴대용 솔루션을 찾고 있습니다.
답변:
종료 후크는 VM이 강제로 종료되지 않은 모든 경우에서 실행됩니다. 따라서 "표준"kill ( SIGTERM
kill 명령에서)을 실행하면 실행됩니다. 마찬가지로을 호출 한 후에 실행됩니다 System.exit(int)
.
그러나 하드 킬 ( kill -9
또는 kill -SIGKILL
)은 실행되지 않습니다. 마찬가지로 (그리고 분명히) 컴퓨터에서 전원을 끌어 내거나 끓는 용암 통에 넣거나 큰 망치로 CPU를 조각 내면 실행되지 않습니다. 그래도 이미 알고있을 것입니다.
종료 자도 실제로 실행되어야하지만 종료 정리에 의존하는 것이 아니라 종료 후크에 의존하여 작업을 깔끔하게 중지하는 것이 가장 좋습니다. 그리고 항상 그렇듯이 교착 상태에주의하십시오 (너무 많은 종료 후크가 전체 프로세스를 중단시키는 것을 보았습니다)!
좋아, 내가 "자바 모니터링 및 관리"로 작업하기로 선택한 모든 가능성
이 여기에있다.
이것은 비교적 쉬운 방법으로 하나의 애플리케이션을 다른 애플리케이션에서 제어 할 수있게 해준다. 제어 애플리케이션을 스크립트에서 호출하여 제어 애플리케이션을 종료하기 전에 정상적으로 중지 할 수 있습니다.
다음은 간단한 코드입니다.
제어 된 응용 프로그램 :
다음 VM 매개 변수를 사용하여 실행합니다.
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port = 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");
}
}
}
응용 프로그램을 제어 :
으로 실행 중지 하거나 시작 명령 행 인수로
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();
}
}
}
그게 다야. :-)
다른 방법 : 애플리케이션이 서버 소스를 열고 정보가 도착할 때까지 기다릴 수 있습니다. 예를 들어 "마법의"단어가있는 문자열 :) 그리고 나서 시스템을 종료하기 위해 반응합니다 : System.exit (). 텔넷과 같은 외부 응용 프로그램을 사용하여 이러한 정보를 socke에 보낼 수 있습니다.
다음은 약간 까다 롭지 만 이식 가능한 솔루션입니다.
Java Agent를 구현했습니다. Github에서 사용할 수 있습니다 : https://github.com/everit-org/javaagent-shutdown
솔루션에 대한 자세한 설명은 https://everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process/에서 확인할 수 있습니다.
Linux에서 시그널링은 "kill"(사용 가능한 시그널에 대해 man kill)로 수행 할 수 있습니다.이를 수행하려면 프로세스 ID가 필요합니다. (ps ax | grep java) 또는 이와 유사한 것 또는 프로세스가 생성 될 때 프로세스 ID를 저장합니다 (대부분의 Linux 시작 파일에서 사용됨, /etc/init.d 참조).
이식 가능한 신호는 Java 애플리케이션에 SocketServer를 통합하여 수행 할 수 있습니다. 그렇게 어렵지 않으며 원하는 명령을 자유롭게 보낼 수 있습니다.
종료 자 대신 finally 절을 의미했다면; System.exit ()가 호출 될 때 실행되지 않습니다. 종료자는 작동해야하지만 실제로 더 중요한 작업을 수행해서는 안되지만 디버그 문을 인쇄해야합니다. 위험합니다.
답변 해 주셔서 감사합니다. Shutdown은 내 경우에 작동하는 것과 같은 이음새를 연결합니다. 그러나 나는 또한 Monitoring and Management Bean이라는 것에 부딪 혔습니다.
http://java.sun.com/j2se/1.5.0/docs/guide/management/overview.html
원격 모니터링과 조작을위한 좋은 가능성을 제공합니다. 자바 프로세스의. (Java 5에서 도입 됨)