2011-04-13 7 views
15

El comportamiento correcto para un cargador de clases en Java es:Clasificadores de Java: ¿por qué buscar primero el cargador de clases padre?

  1. Si ya se ha cargado, devolver la clase
  2. llame al padre loadClass()
  3. Trate de cargar la clase misma.

Por lo tanto, la clase definida en el classpath del sistema siempre debe cargarse primero. Tomcat define el cargador de clases por guerra, que tiene el cargador de clases del sistema como principal, por lo que si intenta cargar una clase, primero buscará en el classpath del sistema y luego en el classpath definido en el archivo war.

Según mi entendimiento, esto es por dos razones:

  1. para evitar problemas con las diferentes versiones de las clases que se utilizan. Imagina que redefiní java.lang.Object en una guerra, sería una pesadilla.
  2. Para evitar dependencias en los cargadores de clase secundarios: El cargador de clases del sistema no puede depender de los cargadores de clase secundarios: sería difícil volver a desplegar una guerra, por ejemplo.

Entonces, la pregunta es:

Además de los problemas anteriores, ¿hay otros peligros para la implementación de un cargador de clases que no hace una búsqueda de los padres en primer lugar?

+1

JFYI: java.lang.Object no se cargaría de la guerra. Hay una comprobación explícita para java.lang en ClassLoader. Solo se puede cargar desde la ubicación de arranque. –

Respuesta

3

No realmente. De hecho, es tan simple como instancias de un URLClassLoader y dándole null para el padre:

myClassLoader = new URLClassLoader(myUrlArray, null); 

http://download.oracle.com/javase/6/docs/api/java/net/URLClassLoader.html

+0

Si prueba 'myClassLoader.loadClass (" [I ")' obtendrá una 'java.lang.ClassNotFoundException', lo cual es bastante sorprendente. –

3

La única otra razón que se me ocurre sería asegurar que la ruta de clase funciona como se esperaba. Al buscar primero el elemento primario, está en efecto colocando la ruta de clase primaria (es decir, la ruta de clase del sistema) antes de la ruta de clases del elemento secundario. Entonces, si especificas jar específicos cuando comienzas el jvm usando -cp, ellos "sombrearán" los frascos que hayas incluido en cualquier archivo que intentes cargar. Si no marca primero el padre, la ruta de clase del hijo sombreará al padre.

0

Si no busca en absoluto a su padre, perderá acceso a todos los objetos Java estándar, y es probable que no pueda ejecutarse en absoluto.

Pero es razonable buscar primero su propio cargador de clases, antes de intentar con el padre. Si desea anular el comportamiento que proporciona una clase anterior, deberá hacerlo de esta manera.

La JVM no, porque la búsqueda de su padre primero tiene más sentido. Sin embargo, si sabes lo que estás haciendo, puedes hacer algunas cosas muy interesantes con cargadores de clases. Eche un vistazo al Classworlds.

13

Tomcat no busca en primer lugar un cargador de clases padre. En realidad, hace lo contrario: primero se ve en la aplicación web y solo luego va al cargador de clases padre (que es "lib" para Tomcat 6/7 y "compartido" para Tomcat 5.5). La excepción para esta regla son las clases del sistema (creo que todo lo que tiene el paquete java. * Y javax. *), Estas clases se buscaron solo en el cargador de clases del sistema. Creo que la razón por la que lo hacen es la razón número 1 que usted indicó.

Así que, básicamente, no está mal para implementar la estrategia de padres y primera. También está bien implementar parent-last. Ambas estrategias tienen sus contras y pros.

Te daré una razón más, ¿por qué poner en práctica padre-en primer lugar: se reduce la cantidad de clases cargadas en la memoria permanente. Imagine que tiene múltiples aplicaciones web que usan la misma biblioteca. Con los padres primero, la biblioteca debe cargarse una vez. Con parent-last se cargará varias veces.
Sin embargo, la primera matriz se requerirá todos los web-apps para utilizar la misma versión de la biblioteca, mientras que con los padres y la última se pueden utilizar diferentes versiones.

+0

Interesante respuesta. Sin embargo, me pregunto cuál es la mejor estrategia para implementar un cargador de última generación. Para implementar Parent-First es bastante sencillo ya que solo necesitaría implementar el método findClass(), y ya está todo listo. Para implementar parent-last, parece que tendrá que anular loadClass (String, boolean) y, probablemente, reproducir muchas de las funcionalidades allí (a excepción de la secuencia de búsqueda de clases). Gracias – RAY

+1

¿Por qué necesita implementar su propio cargador de clases? ¿Qué caso de uso estás tratando de resolver? Estas son las primeras preguntas antes de comenzar a hablar sobre la implementación real. Por lo general, la implementación es impulsada por los casos de uso ... – Tarlog

2

Tarlog es correcta, usted no tiene que hacerlo de esa manera. Java no visualizó casos de uso como tomcat.

Sin embargo, es cuestionable por qué contenedores alojar múltiples aplicaciones en un solo VM. Separar los procesos es más agradable.

Cuestiones relacionadas