¿Es posible captar la señal Ctrl+ Cen una aplicación de línea de comandos de Java? Me gustaría limpiar algunos recursos antes de terminar el programa.
Respuestas:
Puede adjuntar un gancho de apagado a la VM que se ejecuta cada vez que la VM se apaga:
La máquina virtual Java se apaga en respuesta a dos tipos de eventos:
El programa sale normalmente, cuando sale el último subproceso que no es demonio o cuando se invoca el método de salida (equivalentemente, System.exit), o
La máquina virtual se termina en respuesta a una interrupción del usuario, como escribir Ctrl+ C, o un evento en todo el sistema, como el cierre de sesión del usuario o el apagado del sistema.
Sin embargo, el hilo que pasa como gancho de cierre tiene que seguir varias reglas, así que lea la documentación vinculada con atención para evitar cualquier problema. Esto incluye garantizar la seguridad del hilo, la terminación rápida del hilo, etc.
Además, como señala el comentarista Jesper, se garantiza que los ganchos de cierre se ejecuten en el cierre normal de la máquina virtual, pero si el proceso de la máquina virtual se termina por la fuerza, no es así. Esto puede suceder si el código nativo se estropea o si mata a la fuerza el proceso ( kill -9
, taskkill /f
).
Pero en esos escenarios, todas las apuestas están canceladas de todos modos, por lo que no desperdiciaría mucho pensamiento en ello.
TerminateProcess()
o SIGKILL
) pero eso está fuera del funcionamiento normal y, dado que Ctrl + C ya está cubierto por el gancho de cierre, es seguro usarlo. No puede hacer mucho si el sistema operativo realmente termina su proceso de todos modos.
kill -HUP
es la eliminación "más suave" de Unix y debería ejecutar el gancho de cierre. No estoy seguro del valor predeterminado kill
.
Solo para fines de prueba rápida de la consola ...
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
Thread.sleep(200);
System.out.println("Shutting down ...");
//some cleaning up code...
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
});
La respuesta principal sugiere usar un gancho de cierre. Los ganchos de cierre son mucho más problemáticos de lo que valen. Se ejecutan en un orden indeterminado, y las bibliotecas de las que depende pueden agregar sus propios enlaces de cierre, lo que puede significar que algo de lo que depende su propio enlace de cierre se puede desinicializar antes de que se ejecute el enlace de cierre. Ahórrese el dolor de cabeza y use un controlador de señales:
Signal.handle(new Signal("INT"), // SIGINT
signal -> System.out.println("Interrupted by Ctrl+C"));
Signal
es actualmente sun.misc.Signal
, lo que significa que quedará obsoleto, pero el nombre por el que se está reemplazando se llama actualmente jdk.internal.misc.Signal
, por lo que hasta que el equipo de Java descubra cómo exponer públicamente los controladores de señales de una manera no interna, tenga en cuenta que esta llamada puede desaparecer. Sin embargo, por ahora (a partir de JDK 11), sun.misc.Signal
todavía existe.