2012-10-11 70 views
22

He añadido un shutdown hook a través de:gancho de cierre no funciona en Eclipse

Runtime.getRuntime().addShutdownHook(myShutdownHook); 

Funciona bien con normalidad, pero no cuando haga clic en el botón de parada roja en Eclipse. ¿Hay alguna manera de hacer que se llame al enganche de cierre en Eclipse?

+0

las preguntas se marcan como duplicadas a una pregunta que se hizo 2 años más tarde – urir

+0

en realidad la otra dos años antes (09 en lugar de 11). Probablemente leyó mal el día (13) del año. – Christoph142

Respuesta

12

El botón de parada rojo mata a la fuerza de la aplicación, es decir, no con gracia, por lo que la JVM no sabe que la aplicación está saliendo, por lo tanto, los ganchos de cierre no se invocan.

Desafortunadamente, no hay forma (en Windows, al menos) de proporcionar un mecanismo que asegure que el gancho siempre se invoque. Es solo algo que puede invocarse, pero no hay garantía.

+2

Indique una fuente que cite que "no hay forma de proporcionar un mecanismo que garantice que el enganche siempre se invoque", porque la página http://docs.oracle.com/javase/7/docs/api/java/lang/ Tiempo de ejecuciónhtml # addShutdownHook (java.lang.Thread) establece claramente que los ganchos ** se ejecutarán ** cuando "el programa salga normalmente" o que "la máquina virtual finalice en respuesta a una interrupción de usuario/sistema". – Pacerier

+1

@Pacerier Esa declaración se basó en una prueba que hice donde cerré una ventana de la consola que estaba ejecutando un script por lotes invocando una aplicación Java. Al cerrar la ventana, no se invocó el gancho de apagado. –

+2

Esto y detener la aplicación desde Eclipse son ejemplos de programas que * no salen normalmente *. –

4

no se puede obtener en torno al problema mediante el uso de:

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

Por favor, consulte: How to get shutdown hook to execute on a process launched from Eclipse

+2

No puedo pedirle a todo el usuario que agregue una variable de entorno adicional. – urir

+0

Al menos como una solución temporal mientras se depura y experimenta Me gusta esta idea, es mucho más práctico que las otras soluciones para este problema que he encontrado hasta ahora. – Nic

0

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, vea esto issue en eclipse bug tracker.

0

@Pacerier - Del Javadoc: en raras circunstancias, la máquina virtual puede abortar, es decir, dejar de funcionar sin apagarla limpiamente. Esto ocurre cuando la máquina virtual finaliza 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 al, por ejemplo, corromper las estructuras internas de datos o intentar acceder a una memoria inexistente. Si la máquina virtual aborta, no se puede garantizar si se ejecutarán o no los ganchos de cierre.

5

me hizo un corte mediante la sustitución de JavaProcess con un decorado:

IProcess p = launch.getProcesses()[0]; 
    launch.addProcess(new JavaProcessDecorator(p)); 
    launch.removeProcess(p); 

y decorador es reemplazar la función termine.

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(); 
}} 

Al hacer clic en el botón rojo, le envío un mensaje a la aplicación solicitando una terminación suave. Si no funciona, el segundo clic en el botón rojo lo matará.

-1

Si solo quiere probar si el gancho está funcionando o no, throw new RuntimeException() desde el punto de disparo. Esto debería llamar al gancho de apagado incluso desde Eclipse.

1

Sé que llego un poco tarde a la fiesta, pero encontré este hilo en busca de ayuda y probablemente lo harán otros.

Tuvimos el mismo problema y lo solucionamos con un Eclipse plugin (en Linux) que proporciona botones de parada adicionales ahora. Espero que esto sirva a todos ustedes y nos ayudó :)