La ejecución de un programa Java consite en interpretar los
bytecodes, es decir, en transformarlos en código del
sistema y ejecutar ese código conforme se va interpretando. La
JVM es la encargada de realizar esta tarea. Por suerte, el
código a interpretar no es un lenguaje de alto nivel, los
bytecodes son en realidad código máquina escrito para el juego
de instrucciones de la JVM, por lo que el proceso de
interpretación es más rápido que el de otros lenguajes. Además,
la máquina virtual puede emplear los denominados JIT (Just
In Time Compiler), que traducen los bytecodes a código
nativo optimizado una sola vez de modo que cada vez que la JVM
vuelve a invocarlo se ejecuta directamente la versión ya
interpretada.
Antes de que la JVM comience este proceso de interpretación
debe realizar una serie de tareas para preparar el entorno en el
que el programa se ejecutará. Este es el punto en el que se
implementa la seguridad interna de Java.
Hay tres componentes en el proceso:
Cargador de clases. Este elemento se encarga de
separar las clases que carga para evitar ataques. En Java 2
se definen tres grupos de clases asociados a distintas rutas
de búsqueda: clases del sistema (asociadas a la ruta de
arranque o boot class path), clases de extensión
del sistema (asociadas a la ruta de extensión o
extension class path) y clases del usuario o la
aplicación (asociadas a la ruta de clases del usuario o la
aplicación user class path). El orden de búsqueda
de las clases es: sistema, extensión y usuario. Cuando una
clase se encuentra se detiene la búsqueda (una aplicación
sólo podría reemplazar una clase del sistema modificando la
ruta de arranque, y eso no es posible sin tener acceso total
al sistema). El cargador de clases es una clase Java y puede
ser extendida para definir cargadores de clases especiales,
pero sólo por las aplicaciones; si un applet pudiera definir
su propio cargador podría modificar el cargador del sistema
y potencialmente tomar la máquina en la que se
ejecuta el navegador.
Verificador de archivos de clases. La función
de este componente es validar los bytecodes. Aunque esta
tarea podría parecer absurda, no lo es, ya que no todos los
bytecodes tienen por qué ser correctos, pues se pueden
generar a mano o empleando compiladores modificados. El
sistema distingue entre código en el que se confía
(generalmente las clases del sistema y las validadas por el
usuario) y código en el que no se confía. Las clases
consideradas seguras no se validan, pero el resto si. El
verificador de archivos de clases forma parte de la JVM y,
por lo tanto, sólo puede ser reemplazado cambiando la
máquina virtual.
Gestor de seguridad. Se encarga de comprobar el
acceso en tiempo de ejecución. Es una clase del sistema y
puede ser extendida por las aplicaciones. La implementación
por defecto de Java 2 define un sistema basado en políticas
de acceso.