| Java en Tiempo Real |
|
|
|
| Escrito por Leonardo De Seta |
| Martes 29 de Julio de 2008 10:40 |
|
La clave para comprender si una aplicación es de tiempo real tiene que ver con sus requerimientos, y si los mismos incluyen restricciones temporales. Los desarrolladores de la Especificación de Tiempo Real para Java (Real-Time Specification for Java, o RTSF), JSR 1, usan esta definición de ejecución en tiempo real: El entorno de programación debe proveer las abstracciones necesarias para permitir a los desarrolladores manipular correctamente el comportamiento temporal de la lógica de la aplicación. No es necesariamente rápida, pequeña, o de uso exclusivo para el control industrial; todo es acerca de la predecibilidad de la ejecución de la lógica de la aplicación respecto al tiempo. Las aplicaciones en tiempo real suelen ser particionadas en un grupo de tareas, algunos de los cuales tienen metas de tiempo. El objetivo es poder organizar a todas las tareas de tal manera que completen su trabajo antes de sus metas de tiempo. Definiciones: tiempo real inflexible, tiempo real flexibleSe puede clasificar a los sistemas en tiempo real dependiendo de los requerimientos del sistema. Un sistema de tiempo real inflexible es aquel en el cual el sistema tiene que complir todas sus metas de tiempo sin excepción. Usualmente estos sistemas también tienen baja latencia, el tiempo entre que ocurre un evento disparador y se inicia o completa la respuesta a este evento, generalmente medido en microsegundos o milisegundos. Muchos sistemas de tiempo real inflexible se los clasifica como sistemas de seguridad crítica. Estos sistemas se usan para proteger a humanos de resultar heridos o quedar en peligro. Los sistemas de seguridad crítica deben pasar por un testing exhaustivo y revisión de código línea-por-línea antes de ser certificados. La tecnología Java para sistemas de seguridad críticos está siendo estudiada en JSR 302, y actualmente no forma parte de RTSJ. Por otro lado, un sistema de tiempo real flexible es aquel que funcionará correctamente, de acuerdo a su especificación, aunque el sistema ocasionalmente no cumpla con las metas de tiempo. Por ejemplo, el sistema de telefonía celular es de tiempo real flexible: los clientes esperan que se completen todas las llamadas, pero no cumplir con metas de tiempo ocasionalmente puede causar un fallo aceptable, como pausas en el audio o demoras en la llamada. Los sistemas de tiempo real flexible especifican el porcentaje de metas que pueden incumplirse, y qué tan frecuente esto es aceptable. Lo impredecible en las aplicaciones basadas en JavaHay varios factores que llevan a la impredecibilidad de la ejecución de las aplicaciones en el tiempo, y por lo tanto pueden causar que una aplicación Java estándard no cumpla con las metas de tiempo. Las causas más comunes:
Java en Tiempo Real (RTSJ)La Especificación de Tiempo Real para Java (RTSJ), o JSR 1, especifica cómo un sistema Java debería comportarse en un contexto de tiempo real. La especificación fue desarrollada durante varios años por expertos de Java y de aplicaciones en tiempo real. La RTSJ está diseñada para extender la familia Java (toda la plataforma Java, Java SE, Java EE, Java Micro Edition y demás), y tiene el requerimiento de que cualquier implementación debe pasar el Test de Compatibilidad JSR 1 (TCK) y el TCK propio de la plataforma en la cual está basada. Es decir RTSJ extiende naturalmente cualquiera de las plataformas Java existentes. RTSJ introduce varias caraterísticas nuevas para soportar operaciones en tiempo real. Estas características incluyen nuevos tipos de thread, nuevos modelos de gestión de memoria, y otros frameworks también nuevos. Tareas y metas de tiempoRTSJ modela la parte de tiempo real de una aplicación como un grupo de tareas, cada una de las cuales tiene una meta de tiempo opcional. Esta meta de la tarea es cuando la tarea debe ser completada. Las tareas de tiempo real se dividen en varias categorías, basadas en cómo el desarrollador puede predecir su frecuencia y ejecución:
RTSJ utiliza la información de los tipos de tarea en distintas maneras para asegurar que las tareas críticas no incumplan sus metas. Primero, RTSJ permite asociarle a cada tarea un Handler de Meta Incumplida. Si una tarea no se completa antes de su meta de tiempo, se invoca al handler asociado. La información de metas incumplidas puede ser usada para tomar medidas correctivas o reportar información de performance o compartiempo. En comparación con aplicaciones comunes (no de tiempo real), las fallas pueden no resultar aparentes sino por efectos secundarios (como ser timeouts), en cuyo caso puede ser demasiado tarde para arreglar la situación. Un handler se podría configurar así: ReleaseParameters.setDeadlineMissHandler(AsyncEventHandler handler); Prioridades de threadsEn un ambiente de tiempo real, las prioridades de los threads son de extrema importancia. Ningún sistema puede garantizar que todas las tareas vayan a completarse en tiempo. Sin embargo, un sistema de tiempo real puede garantizar que si algunas de las tareas van a incumplir sus metas de tiempo, entonces las tareas de menor prioridad serán las primeras en ser sacrificadas. RTSJ define al menos 28 niveles de prioridad y requiere un cumplimiento estricto de las mismas. Sin embargo, como ya se mencionó, RTSJ depende de un sistema operativo en tiempo real para soportar múltiples prioridades. El problema de la inversión de prioridades puede afectar negativamente a las prioridades. De esta manera, RTJS requeire la herencia de prioridades en su gestión. La herencia de prioridad evita la inversión de prioridades, aumentando la prioridad del thread que está bloqueando un recurso para igual la prioridad del thread de mayor prioridad que está esperando el recurso. Esto evita que un thread de prioridad alta se queda esperando indefinidamente a un thread de menor prioridad que tiene bloqueado el recurso, pero que no puede liberar porque no obtiene los ciclos de CPU necesarios para finalizar su tarea. Además, RTJS está diseñado para permitir que actividades de tiempo real y de no tiempo real coexistan en la misma aplicación Java. El grado de garantías temporales brindadas a una actividad dependen del tipo de thread en la cual se ejecuta la actividad: java.lang.Thread o javax.realtime.RealtimeThread.
Extensiones para la gestión de memoriaUno de los problemas de la gestión automática de memoria de las máquinas virtuales estándard es que una actividad puede "pagar" por el costo de la gestión de memoria de otra actividad. Considérese una aplicación con dos threads: un thread de alta prioridad (H) que realiza un muy poco uso de memoria, y un thread de baja prioridad (L) que utiliza mucha memoria. Si H se ejecuta cuando L ya consumió casi toda la memoria disponible en el heap, el garbage collector puede activarse y consumir tiempo, cuando H sólo iba a asignar un objeto pequeño. Así, H está pagando (en la forma de una demora enorme) por el uso de memoria de L. RTJS provee una subclase de RTT llamada NoHeapRealtimeThread (NHRT). Las instancias de esta subclase están protegidas de interferencias del GC. NHRT está pensanda para actividades de tiempo real inflexible. Para maximizar la predecibilidad, los NHRT no pueden usar el heap gestionado por el garbage collector, no referenciar a este heap. Si lo hicieran, el thread podría sufrir pausas por el GC, lo que podría provocar incumplimientos en la meta de tiempo. En cambio, NHRT utilizan un memoria acotada y memoria inmortal para asignar memoria de una manera más predecible. Áreas de memoriaRTSJ brinda varias formas de reservar memoria para objetos, dependiendo de la naturaleza de la tarea realizando la reserva. Los objetos pueden asignarse a un área de memoria específica, y las diferentes áreas tienen diferentes características de GC y límites de reserva.
¿Por qué memoria acotada?En los programas java es comun reservar memoria para objetos temporales. Por ejemplo, al concatenar dos Strings se genera un StringBuffer que luego es descartado ni bien se transforma a un String. La memoria acotdada permite a una tarea decir "voy a suar esta cantidad de memoria temporal durante el curso de mi tarea, y cuando la tarea esté terminada, reclamala toda". Como la memoria acotada se reserva al comienzo de la tarea, la reserva no fallará. Dado que al finalizar la tarea se libera el área de memoria completa, la liberación es rápida y predecible. Por lo tanto, mientras las aplicaciones pueden estimar cuánta memoria van a necesitar, la memoria acotada permite eliminar la impredecibilidad de la reserva de memoria para objetos. Una desventaja de este tipo de memoria es que, como todos sus objetos desaparecen luego de terminada la tarea, no se pueden guardar referencias a estos objetos en la memoria inmortal o el heap estandard. En un procedimiento similar al de chequeos por null pointers y límites de los arrays, la JVM realiza controles dinámicos para garantizar que un objeto nunca es referenciado por un objeto con un tiempo de vida más largo. Más información |