2010-04-15 12 views
11

Al llamar al loadClass() en un ClassLoader, ¿el ClassLoader primero comprueba si la clase se ha cargado, o delega inmediatamente este cheque a su padre ClassLoader?modelo de delegación Java ClassLoader?

Java API dice:

Cuando solicitó a encontrar una clase o un recurso, una instancia de cargador de clases será delegar la búsqueda de la clase o el recurso a su cargador de clases padre antes de tratar de encontrar la clase o recurso en sí mismo.

Pero hay un capítulo específico sobre el cargador de clases en el libro de Java reflexión en la acción que dice:

Cargador de clases llama findLoadedClass para comprobar si la clase se ha cargado already.If un cargador de clases no encuentra una clase cargada, llama a loadClass en el cargador de clases padre.

¿Cuál es la correcta?

Respuesta

13

Una implementación adecuada cargador de clases será:

  1. Comprobar si la clase ya se ha cargado.
  2. Normalmente, solicite al cargador de clases principal que cargue la clase
  3. Intente encontrar la clase en su propia ruta de clase.

La implementación predeterminada de ClassLoader.loadClass es algo así como:

protected synchronized Class<?> loadClass(String name, boolean resolve) { 
    // First, check if this class loader has directly defined the class or if the 
    // JVM has initiated the class load with this class loader. 
    Class<?> result = findLoadedClass(name); 
    if (result == null) { 
    try { 
     // Next, delegate to the parent. 
     result = getParent().loadClass(name); 
    } catch (ClassNotFoundException ex) { 
     // Finally, search locally if the parent could not find the class. 
     result = findClass(ex); 
    } 
    } 
    // As a remnant of J2SE 1.0.2, link the class if a subclass of the class 
    // loader class requested it (the JVM never calls the method, 
    // loadClass(String) passes false, and the protected access modifier prevents 
    // callers from passing true). 
    if (resolve) { 
    resolveClass(result); 
    } 
    return result; 
} 

Algunas implementaciones cargador de clases será delegación a otros cargadores de clases no es el padre (OSGi, por ejemplo, los delegados a un gráfico de cargadores de clases dependiendo del paquete), y algunas implementaciones del cargador de clases buscarán clases en un classpath local antes de delegar.

+0

Esto no es verdad. Hay muchos modelos válidos de carga de clases como se describe en http://stackoverflow.com/a/245038/632951. Lo que está hablando como "apropiado" es simplemente uno de los modelos. Los otros modelos de hecho no están implementados de esta manera. – Pacerier

+0

Tiene razón, la respuesta era demasiado preceptiva. Agregué un lenguaje más flexible y agregué ejemplos de escenarios en los que un cargador de clases podría desviarse. Gracias por la respuesta. –

1

Esto es básicamente cómo funciona. Se escribe

Foo f = new Foo(); 

En este punto, el cargador de clase determinará si Foo() se han cargado a saber sus bits en la memoria/perm gen. Si ha sido cargado, entonces usa eso. De lo contrario delegarlo en el cargador de clases padre para tratar de resolver la clase. Los bits de esta clase se leen desde el disco y luego se cargan en la memoria. En el siguiente new Foo(), la clase se encontraría ahora en la memoria/cargada.

2

La API de Java es correcta.

Cuando se solicita para encontrar una clase o de recursos, una instancia de cargador de clases se delegado de la búsqueda de la clase o recursos a su cargador de clases padre antes de tratar de encontrar la clase o propio recurso.

Desde el Java Classloading Mechanism -

Al cargar una clase, un cargador de clases primeros "delegados" la búsqueda de la clase a su cargador de clases padre antes de tratar de encontrar la propia clase.

+0

Estoy confundido, ¿significa que la respuesta dada por @bkail es incorrecta? –

0

Para coincidir con la respuesta de Sri, siempre será delegada al padre y la API es correcta. Si juegas con la carga de clases, esto puede hacer que las cosas sean un poco complicadas para hacer las cosas bien o lograr los efectos que buscas. Sugiero comenzar el jvm con un classpath mínimo y luego cargar todas las clases con su cargador de clases personalizado, la forma más fácil de hacerlo es usar un URLClassloader o un objeto compuesto que envuelva un cargador URLC para que pueda rastrear qué clases están cargadas y cuando.

También vale la pena tener en cuenta que una clase A cargada por el cargador de clases C! = Clase A cargada por el cargador de clases C si C y D no son parte de la misma jerarquía del cargador de clases-padre-hijo.

2

Las dos afirmaciones no son mutuamente excluyentes. La clase solo existirá en el conjunto de clases cargadas del ClassLoader actual si el ClassLoader primario no hubiera podido encontrar la clase anteriormente. Así,

Cuando solicitó a encontrar (los datos externos que describe) una clase o de recursos, una instancia de cargador de clases se delegado de la búsqueda de (los datos externos que describe) la clase o recursos a su clase padre cargador antes de intentar encontrar (los datos externos que describen) la clase o el recurso en sí.

cual no quiere evitar que los cortocircuitos si se conoce su padre no puede encontrar la clase pero puede (como se muestra por ella previamente la carga de la clase)

0

Hay una cuestión más que debe estar observado en este contexto. La documentación del API dice:

Los métodos y constructores de objetos creados por un cargador de clases de mayo de referencia otras clases. Para determinar la clase o clases a las que se hace referencia, la máquina virtual Java invoca el método loadClass del cargador de clase que creó originalmente la clase.

Lo que significa que las redes de clases de referencia son cargadas por el mismo cargador de clases.

+0

¿No significaría eso: "la máquina virtual Java invoca el método loadClass del cargador de clases que creó originalmente la clase", que luego delegará inmediatamente en el cargador de clases padre? –

Cuestiones relacionadas