java - tag - El gancho de apagado no funciona en Eclipse
javadoc todo (7)
Esta pregunta ya tiene una respuesta aquí:
He añadido un gancho de cierre a través de:
Runtime.getRuntime().addShutdownHook(myShutdownHook);
Normalmente funciona bien, pero no cuando hago clic en el botón rojo de detención en Eclipse. ¿Hay una manera de hacer que el gancho de cierre se llame en Eclipse?
@Pacerier - Desde el Javadoc: en raras ocasiones la máquina virtual puede abortar, es decir, dejar de funcionar sin apagarse limpiamente. Esto ocurre cuando la máquina virtual se termina externamente, por ejemplo con la señal SIGKILL en Unix o la llamada TerminateProcess en Microsoft Windows. La máquina virtual también puede abortar si un método nativo falla, por ejemplo, al corromper las estructuras de datos internas o al intentar acceder a una memoria inexistente. Si la máquina virtual se interrumpe, no se puede garantizar si se ejecutarán o no los enganches de apagado.
El botón rojo de parada mata la aplicación a la fuerza, es decir, no correctamente, por lo que la JVM no sabe que la aplicación está saliendo, por lo que no se invocan los ganchos de apagado.
Desafortunadamente, no hay forma (al menos en Windows) de proporcionar un mecanismo que garantice que el gancho siempre se invoque. Es solo algo que puede ser invocado, pero no hay garantía.
El botón rojo de parada simplemente finaliza la aplicación y, de acuerdo con los desarrolladores de eclipse, no pueden hacer nada al respecto; ver este issue en el eclipse bug tracker.
Hice un hack al reemplazar JavaProcess con uno decorado:
IProcess p = launch.getProcesses()[0];
launch.addProcess(new JavaProcessDecorator(p));
launch.removeProcess(p);
Y el decorador está anulando la función de terminación.
public class JavaProcessDecorator implements IProcess {
private IProcess p;
public JavaProcessDecorator(IProcess p) {
this.p = p;
}
private boolean sigkill = false;
@SuppressWarnings("rawtypes")
@Override public Object getAdapter(Class arg) { return p.getAdapter(arg); }
...
@Override public ILaunch getLaunch() { return p.getLaunch(); }
@Override public IStreamsProxy getStreamsProxy() { return p.getStreamsProxy(); }
@Override public void setAttribute(String s1, String s2) { p.setAttribute(s1, s2); }
@Override public void terminate() throws DebugException {
if(!sigkill) {
try {
IDebugIService cs = DirmiServer.INSTANCE.getRemote("main", IDebugIService.class);
if(cs != null) cs.modelEvent(new TerminateRequest());
} catch (RemoteException e) { }
this.sigkill = true;
} else p.terminate();
}}
En primer lugar, haga clic en el botón rojo, le envío un mensaje a la aplicación solicitando la finalización suave. Si no está funcionando, el segundo clic en el botón rojo lo matará.
No puedes solucionar el problema usando:
if (Boolean.parseBoolean(System.getenv("RUNNING_IN_ECLIPSE")) == true) {
System.out.println("You''re using Eclipse; click in this console and " +
"press ENTER to call System.exit() and run the shutdown routine.");
try {
System.in.read();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.exit(0);
}
Consulte: Cómo hacer que el gancho de cierre se ejecute en un proceso iniciado desde Eclipse
Sé que llego un poco tarde a la fiesta, pero encontré este hilo en busca de ayuda y probablemente también otros.
Tuvimos el mismo problema y lo resolvimos con un complemento de Eclipse (en Linux) que ahora proporciona botones de detención adicionales. Espero que esto les sirva a todos tan bien como nos ayudó :)
Si solo desea probar si el gancho está funcionando o no, throw new RuntimeException()
desde el punto de activación. Esto debería llamar al gancho de apagado incluso desde Eclipse.