![]() Versión: 2.0, Septiembre, 2006 Juan Manuel Fernández Luna Web: http://decsai.ugr.es/~jmfluna, Mail: jmfluna@decsai.ugr.es |
![]() ![]() ![]() (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.
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.
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.