Página siguiente Página anterior Índice general

6.6 El cargador de clases

El cargador de clases es el responsable de encontrar y cargar los bytecodes que definen las clase. Una vez que se cargan, los bytecodes son verificados antes de que se puedan crear las clases reales.

Los cargadores de clases son a su vez clases Java, pero, ¿como se carga el primero?. En principio una máquina virtual Java debe incluir un cargador de clases primario, que es el encargado de arrancar el sistema de carga de clases. Este cargador estará escrito en un lenguaje como el C y no aparece en el contexto Java. El cargador primario carga las clases del sistema de archivos local de modo dependiente del sistema.

El cargador de clases cumple también varias tareas relacionadas con la seguridad:

La implementación por defecto del ClassLoader del JDK busca las clases según los siguientes pasos:

  1. Comprueba que la clase no está cargada.
  2. Si la clase no está cargada y el cargador actual tiene un cargador padre, se la pide a este y si no al cargador principal.
  3. Llama a un método personalizable para intentar encontrar la clase de otra forma.
Si después de estos pasos la clase no se ha encontrado se lanza una excepción ClassNotFound.

El sistema determina el tipo de cargador a emplear del siguiente modo:

Para crear un ClassLoader personalizado basta implementar el método loadClass en una subclase:

protected abstract Class loadClass(String name, boolean resolve) throws ClassNotFoundException

En el método hay que realizar cinco operaciones:

  1. Comprobar si la clase está cargada
  2. Si no lo está, cargamos los datos de la clase según el método que queramos (por ejemplo mediante una consulta a una base de datos).
  3. Llamamos al método defineClass() para convertir los bytes en una clase.
  4. Resolver la clase invocando el método resolveClass().
  5. Retornamos la nueva clase creada.

A continuación se presenta un esquema del método loadClass comentado antes:



// método loadClass()
protected Class loadClass(String nom, boolean res) throws ClassNotFoundException { 
  // -- Paso 1 --
  Class c = findLoadedClass (nom);
  if (c == null) {
    try {
      c = findSystemClass (nom);
    } catch (Exception e) {
      // Ignoramos excepciones
    }
  }
  if (c == null) {
    // -- Paso 2 --
    byte datos[] = cargarClase(nom);
    // -- Paso 3 --
    c = defineClass (nom, datos, 0, datos.length);
    if (c == null)
      throw new ClassNotFoundException (nom);
    // -- Paso 4 --
    if (res)
      resolveClass (c);
  }
  // -- Paso 5 -- 
  return c;
}

Para usar el cargador se escribiría un fragmento de código similar al siguiente:

ClassLoader cargador = new MiClassLoader(parametros);
Class c = cargador.loadClass ("MiClase", true);
MiClase mc = (MiClase)c.newInstance();

Para evitar tener que escribir nuesto propio cargador de clases el JDK 1.2 introduce el URLClassLoader, que es una subclase de SecureClassLoader. Con esta clase podemos cargar cualquier clase que pueda ser localizada mendiante un URL (file:, http:, jar:, etc). Si lo que necesita el programador es hacer una operación como encriptar u obtener la clase de una BDA, puede hacerlo con una subclase de la clase URLClassLoader.

Para usar un URLClassLoader sólo es necesario decirle al cargador donde están las clases, no hace falta hacer una subclase a menos que se tengan requisitos muy especiales. Los URLs que terminan con / se consideran directorios y cualquier otra cosa se intenta cargar como archivo JAR.

A continuación se presenta un ejemplo de uso:

try {
  URL listaURLsList[] = {
    new URL ("http://www.iti.upv.es/clases/"),
    new URL ("http://case.iti.upv.es/Monkey.zip"),
    new URL ("http://torpedo.upv.es/luis/norte/"),
    new File ("misClases.jar").toURL()
  };
  ClassLoader cargador = new URLClassLoader (listaURLs);
  Class c = cargador.loadClass("MiClase");
  MiClase mc = (MiClase) c.newInstance();
} catch (MalformedURLException e) {
  // cargar la clase de otra manera o error
}

Página siguiente Página anterior Índice general