2011-12-19 15 views
5

¿Hay alguna forma de garantizar que todo el proceso Java se cerrará si se produce un bloqueo de la zona activa?Cómo forzar el proceso de Java para que salga de la falla de la zona activa

Estamos alojando una biblioteca nativa en un proceso remoto de Windows Java (java.exe), a los fines del aislamiento del proceso. Sin embargo, hemos descubierto que incluso cuando hay un bloqueo de punto de acceso, aunque el hilo principal "muere" con un bloqueo de punto de acceso, el proceso en sí no muere. Tenemos que matarlo en el Administrador de tareas.

Creemos que esto se debe a que la propia biblioteca nativa crea sus propios hilos que mantienen vivo el proceso.

Queremos que todo el proceso de Java se muera si se produce un bloqueo de punto de acceso.

Nuestro trabajo actual consiste en tener otro hilo que lea la salida del proceso generado (tenemos que leer la salida de la consola de todos modos para evitar que el proceso se bloquee). Hemos modificado que también buscan explícitamente un accidente VM:

private static String HOTSPOT_CRASH = "# A fatal error has been detected by the Java Runtime Environment"; 

public void run() { 
    try { 
     BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 
     String line; 
     do { 
      line = reader.readLine(); 
      if (line != null) { 
       logger.info(prefix + ": " + line); 
      } 
      if(line.contains(HOTSPOT_CRASH)) { 
       logger.error(String.format("FATAL Hotspot crash detected. Killing child process '%s'...", hostProcess)); 
       hostProcess.destroy(); 
      } 
     } while (line != null); 
     reader.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

pero esto es un truco: Si la JVM sabe lo suficiente para cerrar la sesión que ha habido un accidente, sería mucho mejor si se pudiera dijo que terminar el proceso actual también.

¿Hay alguna manera de hacerlo? Idealmente, sería una opción de línea de comando para la JVM.

+3

Un proceso no se puede bloquear parcialmente. Es casi seguro que haya dos procesos allí. –

+0

¡problema interesante! un choque es un bloqueo, por lo que no puede hacer mucho si sucede. Probablemente construiría un monitor de latido (el niño envía un mensaje de ping al padre, y el padre envía pong cada pocos minutos). en ausencia de un latido del corazón, salga. – aishwarya

+0

@Ingo - desafortunadamente yo también lo pensé. Pero resulta que estamos teniendo un bloqueo de punto de acceso, pero el proceso aún se mantiene. Solo cuando lo matamos en el Administrador de tareas realmente desaparece. –

Respuesta

0

Por lo general, una máquina virtual saldrá cuando se haya detectado un error fatal pero puede evitar esto en su código. Aquí hay un par de pistas:

  • Marque el proceso principal. En Unix, un niño solo puede morir cuando el padre procesa la señal SIGCHLD (que le dice al padre que el niño ha terminado, esto permite que el proceso principal lea el código de salida, por ejemplo).

    Asegúrese de procesar la salida y de llamar al waitFor() al menos una vez que el niño haya muerto. Eso debería limpiar el proceso del niño.

  • Busque hilos que no sean daemon. Si tiene hilos no-daemon en su aplicación Java, pueden evitar que la VM se cierre.

    Pero un error de VM terminará todos los hilos, así que supongo que nunca se limpia el proceso secundario.

+0

Estamos comunicándonos con el proceso hijo a través de un socket TCP. Si el proceso secundario encuentra un error de zona activa, queremos que el subproceso en el proceso principal que está leyendo desde el socket obtenga un mensaje Connection-reset-by-peer. Una vez que se consigue eso, podemos limpiar el proceso secundario. –

+0

El problema en este momento es que el proceso principal no tiene manera de saber siquiera que el proceso hijo se ha bloqueado: la llamada de "lectura" del socket simplemente espera para siempre, hasta que eliminemos el proceso en el Administrador de tareas. –

Cuestiones relacionadas