java Un vistazo más profundo a la arquitectura J2ME: CLDC
Versión: 2.0, Septiembre, 2006

Juan Manuel Fernández Luna
Web: http://decsai.ugr.es/~jmfluna, Mail: jmfluna@decsai.ugr.es
IndiceInicioPerl

(C) Decsai
Web: http://decsai.ugr.es

Como ya hemos visto, J2ME se sustenta en dos bloques principales: la configuración y el perfil. Volviendo a repasar estos conceptos, una configuración define la plataforma mínima necesaria para un grupo de dispositivos que tienen similar memoria y capacidades de procesamiento. Se compone de una máquina virtual, unas características del lenguaje Java y un conjunto mínimo de clases que soporta ese grupo de dispositivos. Por otro lado, un perfil extiende una configuración y completa las necesidades específicas para una cierta familia de dispositivos. Un perfil tiene asociado un conjunto específico de bibliotecas mínimas.

Configuraciones

J2ME presenta dos configuraciones: CLDC y CDC. La primera se dedica a dispositivos con estrictas limitaciones de memoria, capacidad de cálculo, consumo y conectividad de red. Por otro lado, CDC se encarga de dispositivos con más potencia. Parte de CLDC es un subconjunto de CDC, por lo que la portabilidad de aplicaciones se puede conseguir cuando nos movemos de un entorno más restringido a otro más rico. De la misma manera, y siguiendo en el hilo de la portabilidad, una aplicación en J2ME podrá ejecutarse en J2SE normalmente, salvo que se utilicen las bibliotecas específicas de J2ME.

CLDC

Veamos más detalladamente algunas características de CLDC, ya que es la configuración en la que nos centraremos en este curso. Comencemos por las propiedades mínimas requeridas a un dispositivo para poder desarrollar con esta configuración:

Al tener como objetivo dispositivos con prestaciones reducidas, CLDC elimina una gran cantidad de características que sí aparecen en J2SE, tanto en el propio lenguaje Java como en la máquina virtual, como por ejemplo:

Pero ¿qué razones se consideraron para eliminar esas prestaciones? Por supuesto, una de ellas se basa en cuestiones de ahorro de memoria, ya que el tamaño general del API queda reducido. Aunque otras también han sido quitadas por cuestiones de aligerar el procesador, como es el caso de las operaciones en punto flotante, o la verificación de las clases. Concretamente, esta operación, que identifica y rechaza ficheros de clases inválidas, se realizaba en la máquina virtual en la edición J2SE, pero en ese caso aumenta su tamaño. Por esta razón, en J2ME la verificación se hace en dos partes: la primera, la preverificación, en un ordenador distinto; la segunda sí se lleva a cabo en el propio dispositivo, pero en este caso es mucho más simple y rápida.  Más adelante estudiaremos de manera más detallada el proceso de verificación.

Con respecto a la seguridad, al no definir CLDC completamente el sistema de seguridad de Java deben eliminarse prestaciones que sí figuran en el J2SE (por ejemplo, JINI, que permite la utilización de una biblioteca de clases escrita en otros lenguajes -enlazado en tiempo de ejecución) y que harían muy vulnerables las aplicaciones. Por ejemplo, sin este modelo de seguridad, un cargador de clases definido por el usuario podría alterar la forma en que el camino de las clases fuera recorrido, pudiendo una aplicación sustituir trozos de las bibliotecas del núcleo de Java y ganar acceso al dispositivo de tal forma que pudiera dañarlo.

También se considera la simple conveniencia como criterio: algunas clases pueden ser desarrolladas por los programadores basadas en otras que sí se mantienen. Igual ocurre con algunos métodos de clases. Por otro lado, otras clases se eliminan por que no tiene razón de ser: java.io.File tiene sentido si se trabaja en un sistema de ficheros, pero muchos dispositivos no disponen de él. En su lugar, CLDC utiliza las propias prestaciones del dispositivo.  Otro ejemplo en este sentido son la finalización de objetos, ya en el J2SE puede ocurrir que nunca se lleve a cabo. La eliminación de gestión de errores, por último, va en la linea de la utilidad de la acción, y del tiempo consumido en ello. Una excepción es un error que puede ser recuperable; un error, por el contrario, representa problemas muy serios y generalmente dependientes directamente del dispositivo, por lo que no merece la pena hacerlo.

En cuanto a la máquina virtual de CLDC, KVM, requiere entre 40 y 80 Kbytes dependiendo de las opciones de compilación y el tipo de dispositivo para el que se compile.  Esto implica que se podrán ejecutar aplicaciones con un total de 128 Kbytes. Aparte de esto, se necesitan otros 32 Kbytes para memoria dinámica de la aplicación a ejecutar. KVM está implementada en C y está diseñada para ser tan completa y rápida como sea posible. De hecho, puede ejecutarse de un 30 a un 80% de la velocidad de la JVM.

Volviendo a la verificación de clases, la máquina virtual de Java estándar efectúa un proceso en tiempo de ejecución que se denomina verificación de clases, el cual se lleva a cabo antes de cargar ninguna clase en memoria. El objetivo es asegurar la integridad de los ficheros donde se almacena una clase Java y que el código en ella no intente acceder a memoria fuera de su espacio de nombres, eliminando la posibilidad de que pueda sustituir alguno de los paquetes del núcleo de Java (java.* o javax.*), y poniendo así en juego la seguridad del sistema.  Esta etapa juega un papel muy importante en el modelo de seguridad de Java.

Para que nos hagamos una idea, J2SE verifica, entre otros, estos puntos:

Si nos trasladamos a CLDC, este proceso será muy costoso en términos de uso de recursos, ya que requiere mucha memoria, procesador y espacio para código binario.  Es por esto por lo que los diseñadores de KVM decidieron hacer la verificación de clases de manera diferente a como se hace con JVM. Así, antes de que la clase se llegue a emplear en el dispositivo, ésta es modificada externamente por una utilidad "preverificadora". La idea es añadir al fichero clase generado por javac nuevo código que identifique la clase como válida (pasa a ser una clase verificada). Seguidamente, se transfiere al dispositivo y la KVM sólo tiene que comprobar si esta información está o no presente o contiene o no la información correcta. En cualquiera de los dos casos negativos, el proceso de carga se interrumpe y se lanza una excepción. Esta comprobación se puede hacer justo cuando se carga la clase o como parte del proceso de instalación de la aplicación. En cualquier caso es un proceso más rápido que la preverificación y requiere menos memoria.