2012-04-09 15 views
5

En Java util logging, inicio el controlador en init() y cierro el controlador en destroy() y funciona perfectamente bien: se creó un archivo de registro, etc. Si el usuario actualiza la página normalmente, solo crea un archivo de registro.Java applet: Cómo asegurarse de que la destrucción finalice antes de la actualización de la página

Sin embargo, si el usuario refresca la página con el applet un par de veces rápido, parece que destroy() no se llama o quizás no ha terminado la tarea y desde que se llama de nuevo a init(), asume que el archivo anterior todavía está bloqueado y crea un nuevo archivo de registro.

Intenté usar tanto destroy() como finalize() para cerrar el controlador pero no funciona. ¿Alguien tiene alguna idea de cómo resolver este problema?

Otra pregunta menor es: ¿Qué pasó realmente si init() no ha finalizado y la página se actualiza? ¿Va a continuar el proceso y eventualmente falla al llamar a destroy() o simplemente se detiene allí mismo?

+0

¿Podría agregar al código de pregunta de sus métodos "init" y "destruir"? Al menos partes sobre el manejador de registro. –

Respuesta

4

Presupuesto de Java Tutorials:

El software de Java Plug-in crea un subproceso de trabajo por cada Java applet de .

En el entorno multiproceso, debe tener mucho cuidado con los recursos compartidos. El mejor y más fácil enfoque es no compartir nada (escala lo mejor posible y no hay puntos muertos posibles).

Supongo que inicializa su manejador cada vez en "init" -metodo. Si es cierto, debe usar un registrador compartido estático (marque link). Ayudará a mejorar la situación un poco, pero si inicia más de un navegador con su applet, se creará un nuevo archivo de registro. Y esta solución no es recomendada por Oracle y se conserva para compatibilidad con versiones anteriores.


Solución recomendada y fácil de implementar: "cada applet debe tener su propio registrador y escribir en su propio archivo". Código para la generación de nombres de archivo de registro:

private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); 

private String generateFileName() { 
    return String.format("applets-log/%s-%s.log", dateFormat.format(new Date()), UUID.randomUUID()); 
} 

Además, Best Practices For Applet Development.


respuesta a su pregunta menor (cambió):

De acuerdo con la discusión de este old bug en el plugin de Java y JavaScript podría ser terminado en cualquier momento con un intervalo predefinido para la limpieza. Por lo tanto, debe poner el código de limpieza de recursos en su método "detener" o "destruir", pero no debe confiar en el código que se ejecutará.

applets ciclo de vida es controlada por el navegador y los applets no debe ser capacidades dadas a ejecutar cuando su documento de alojamiento es destruido por navegador.

Desde 6u10, tanto plugin antiguo y nuevo plugin cumplir applet de apagado después de una cantidad fija de tiempo (1000 ms en el viejo plugin y 200 ms en nuevo plug-in) para el subprograma se detengan.

+0

Eso es lo que estaba diciendo. –

0

Espero que no estés probando en FF. Lea aquí: https://bugzilla.mozilla.org/show_bug.cgi?id=638070

+0

ese no es el caso, ya que el applet funciona perfectamente normal, no importa cuántas veces presiones refresh, el applet sigue funcionando. Simplemente no mata el archivo lck y hace que cree varios archivos de registro – Harts

0

Simplemente se ha topado con una limitación fundamental con entornos de subprocesos múltiples.

Usted realmente no puede decir cuándo se llamará destroy() o finalize() en relación con otros hilos. Cuando el navegador vuelve a cargar la página, puede cargar el applet en un nuevo hilo. Si el usuario accede a recargar dos veces rápidamente, puede crear 2 nuevos hilos, llame al init() en el 2º (que el usuario realmente ve) antes de llamar al init() en el que el usuario nunca ve y antes de llamar al destroy() en el anterior. En el otro extremo del ciclo de vida, el hilo de recolección de basura llama al finalize(), posiblemente mucho después de que el objeto ya no se necesite. Está trabajando en un entorno de subprocesos múltiples y no puede contar con ningún orden de operaciones entre subprocesos.

Para citar el Javadoc:

Un applet es un pequeño programa que está destinado para que no funcione por sí mismo, sino más bien para ser integrado dentro de otra aplicación.

Es realmente la aplicación externa la que debe controlar la creación/apertura y cierre del registro si solo va a tener un archivo de registro. Si la aplicación externa es un navegador web, entonces no puede resolver el problema que está teniendo. Por otra parte, si está ejecutando el applet en un navegador web, no debe escribir registros en el sistema de archivos. Eso es solo un comportamiento descortés.

Si absolutamente debe tener archivos de registro para applets dentro de un navegador web, la solución más fácil es para cada llamada al init() para crear un nuevo archivo específico para esa invocación del applet. Si quisiera ambicioso, podría usar los archivos de bloqueo para indicar qué archivos estaban en uso y al destroy() concatenar los archivos de registro desbloqueados en uno más grande, pero nuevamente tiene el problema de coordinar los procesos de concatenación entre subprocesos.

+0

Se equivoca con 'Si la aplicación externa es un navegador web, entonces no puede resolver el problema que está teniendo". Los marcos de registro (JUL, log4j y etc.) son seguros para usar. Por lo tanto, el problema podría resolverse utilizando un registrador compartido estático que será utilizado por todas las instancias de applet. –

+0

@Vadim no puede garantizar que el navegador solo llame a su inicializador estático una vez. El navegador es libre de crear un nuevo cargador de clases de applet y volver a cargar su applet en cada actualización, llamando así a los inicializadores estáticos cada vez. Incluso si en la práctica no funciona, no debe confiar en que los inicializadores estáticos se llamen solo una vez para sincronizar las instancias de los applets. ¿Qué sucede si, por ejemplo, tiene el mismo applet cargado en la misma computadora al mismo tiempo en dos navegadores diferentes, por ejemplo, Firefox y Chrome? –

+0

Variable estática inicializada por JVM, en el momento en que se cargó la clase. No espero ningún problema con el cargador de clases en esta pregunta SO, entonces cambio a la discusión de JVM. Si el usuario inicia 2 navegadores diferentes, cada navegador inicia su propia JVM.También se podría iniciar una JVM nueva si el applet requiere JRE específico o parámetros específicos de JRE (esta condición está bien para la pregunta actual, porque discutimos un applet, por lo que los requisitos y parámetros de JRE serán los mismos). Por lo tanto, la variable estática compartida funcionará en el caso de un navegador y el problema de la pregunta aparecerá en el caso de varios navegadores. –

Cuestiones relacionadas