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:
java.*
es el cargador primario, de hecho,
todas las clases de este paquete tienen un cargador de
clases null
. Este hecho es importante para la
seguridad por dos razones: en primer lugar nos garantiza que
se cargaran correctamente, algo muy importante, ya que son
básicas para el correcto funcionamiento del sistema, y en
segundo tambien nos asegura que se cargarán del sistema de
archivos local, lo que evita que una aplicación remota pueda
reemplazarlas.La implementación por defecto del ClassLoader
del JDK
busca las clases según los siguientes pasos:
ClassNotFound
.
El sistema determina el tipo de cargador a emplear del siguiente modo:
URLClassLoader
.AppletClassLoader
.java.lang.Class.ForName
, se emplea el cargador
principal.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:
defineClass()
para convertir
los bytes en una clase.resolveClass()
.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
}