Java ShutdownHook no se puede unir Tema principal cuando se ejecuta desde JNI

Jeff G:

Tengo algo de código Java para crear un gancho de cierre con el fin de salir limpiamente cuando las prensas cliente Ctrl + C:

private static void shutdownHandler(Thread mainThread) {
    try {
        mainThread.join(30000);
    } catch (InterruptedException e) {
    }
}

public static void main(String[] args) {
    final Thread mainThread = Thread.currentThread();
    Thread shutdownThread = new Thread(() -> shutdownHandler(mainThread));
    Runtime.getRuntime().addShutdownHook(shutdownThread);
}

Cuando ejecuto esto desde la línea de comandos, funciona como se esperaba (las principales salidas de hilo y vuelve casi inmediatamente a la línea de comandos). Sin embargo, si escribo un envoltorio de JNI que llama a este mediante el siguiente código C ++ en su lugar:

JavaVMInitArgs vm_args;
// Populate vm_args

JavaVM *jvm;
JNIEnv *env;
JNI_CreateJavaVM(&jvm, reinterpret_cast<void**>(&env), &vm_args);

jclass mainClass = env->FindClass("path/to/my/class");
jmethod mainMethod = env->GetStaticMethodID(mainClass, "main", "([L" STRING_CLASS ";)V");

jclass stringClass = env->FindClass(STRING_CLASS);
jobjectArray mainArgs = env->NewObjectArray(0, stringClass, NULL);

env->CallStaticVoidMethod(mainClass, mainMethod, mainArgs);
jvm->DestroyJavaVM();

A continuación, los shutdownHandlercuelga método hasta los 30 transcurre segundo de tiempo de espera, a continuación, devuelve el control al código C ++ y eventualmente salidas. ¿Alguien sabe de una manera de permitir que el shutdownHandlermétodo para unir el hilo principal cuando se arranca desde una llamada JNI?

Holger:

En el primer ejemplo, las principales salidas de rosca, a continuación, la JVM detecta que no hay hilos no Daemon derecho e iniciará el cierre de JVM. En este momento, no hay ningún problema de unirse al hilo principal, ya que ha terminado incluso antes de la desconexión.

En su segunda variante, el hilo principal, es decir, el hilo que ejecuta el mainmétodo a través env -> CallStaticVoidMethod(…), es ocupado ejecutando jvm -> DestroyJavaVM(). Dado que la función de espera para la realización de los manipuladores de apagado y que espera el controlador de parada para la realización de este hilo, que tiene un punto muerto.

Usted puede obtener un comportamiento similar con código Java puro también. Cuando se coloca System.exit(0);al final del mainmétodo, dejando que el hilo principal iniciar el apagado y esperar a su finalización, se obtiene un punto muerto similar.

En general, no debe realizar joinla operación en los manejadores de apagado. Estos controladores se supone que limpiar y volver lo más rápido posible.

O, como los de documentación pone:

ganchos de apagado se ejecutan en un momento delicado en el ciclo de vida de una máquina virtual y, por tanto, deben codificarse defensiva. Deben, en particular, pueden escribir a ser flujos seguros y evitar los puntos muertos en la medida de lo posible. Asimismo, no deben confiar ciegamente en los servicios que pueden haber registrado sus propios ganchos de cierre y por lo tanto pueden por sí mismos en el proceso de apagado. Los intentos de utilizar otros servicios basados ​​en hilo como el hilo de eventos AWT-expedición, por ejemplo, puede conducir a puntos muertos.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=186021&siteId=1
Recomendado
Clasificación