2012-05-13 8 views
6

Tengo dos webapps diferentes, y cada una carga la misma clase A con un cargador de clases diferente. Cuando pongo una instancia en la sesión y luego la obtengo de la otra aplicación web, se lanza un ClassCastException.Cómo emitir dos instancias del mismo cargador de clases cargado diferente?

Por ejemplo, en la aplicación de web A, almaceno a en la sesión, a continuación, en la aplicación de web B, consigo el a de la sesión y echarlo a A, el ClassCastException se lanza.

¿Hay alguna manera de resolver esto?

Respuesta

3

Básicamente, debe evitar esta situación: coloque ambos bits de funcionalidad en la misma aplicación web o mueva la biblioteca que contiene la clase A a una ubicación adecuada de modo que solo se use un cargador de clase. Dos clases cargadas por diferentes cargadores de clases son completamente distintas en la JVM; usted simplemente no podrá ser capaz de transmitir entre ellas.

Consulte el Tomcat classloader documentation para obtener más información sobre los diversos cargadores de clases utilizados. Parece que desea colocar esta clase común en el área de cargador de clases común. Como se señala en la documentación, esto es bastante inusual, pero si realmente desea compartir un objeto entre dos aplicaciones web (que es también inusual), es probablemente la forma más fácil de hacerlo.

5

¿Hay alguna manera de resolver esto?

Básicamente no.

Por lo que se refiere al JLS, los tipos son diferentes y no hay forma de que la JVM le permita pretender lo contrario. Por ejemplo, las clases podrían tener diferentes códigos y diseños de objetos diferentes. Si pudieras engañar a la JVM para que tratara los tipos como iguales, serías capaz de eliminar la seguridad de tiempo de ejecución de JVM. De esa manera yace la locura.

La solución es asegurarse de que no tenga dos cargadores de clases diferentes cargando la misma clase. En el contexto de Tomcat, esto significa que si dos o más aplicaciones web necesitan compartir instancias de una clase, entonces esa clase se debe definir en un cargador de clases que sea común a ambos; p.ej. ponga el archivo JAR en el directorio $CATALINA_HOME/lib o $CATALINA_HOME/common.


Si hay una buena razón por qué las clases tienen a ser cargados por diferentes cargadores de clases (tal vez porque las clases son en realidad diferente), entonces se podría solucionar el problema mediante la definición de una interfaz que ambas versiones de la implementar en clase, y luego programar en la interfaz en lugar de la clase de implementación. Por supuesto, solo puede haber una versión de esa interfaz cargada ... o de lo contrario se encuentra con el mismo problema nuevamente.

1

No puede. Dos clases cargadas por diferentes clasificadores son diferentes.

0

¿Quizás pueda serializar los objetos compartidos?

No estoy necesariamente abogando por este enfoque, pero por otra parte eso es lo que básicamente hace serialización --- serializa de algunos JVM o cargador de clases X y lo carga en (deserializar) en otra JVM/cargador de clases Y ...

+0

Creo que la serialización puede funcionar, pero finalmente uso CAS para resolver este problema. :) – xiaolg2008

0

No se puede emitir dos objetos de diferentes clases, incluso si las clases tienen el mismo nombre de paquete y la firma, sin embargo, puede copiar los datos de una a otra simplemente mediante el uso de la biblioteca Apache frijol utils, BeanUtils.copyProperties(o1, o2);

0

Este es posible con una solución alternativa.

Si bien es cierto que no puede convertir un objeto de una clase cargada por el cargador de clases A a la misma clase cargada por el cargador B (las clases con el mismo nombre no son compatibles si está cargado bajo diferentes cargadores de clases como explained here), un contenedor de aplicaciones web como Jetty o Tomcat, puede cargar esa clase una vez en un cargador de clases principal, que será utilizado por todas las aplicaciones web en la JVM. Cada cargador de clases de aplicaciones web diferirá al cargador de clases compartido (principal) para la definición de clase y su conversión de ida y vuelta funciona bien.

Por ejemplo, con Jetty, use WebAppContext.addSystemClass() como se describe here.

Cuestiones relacionadas