java - reales - ¿Cómo funciona la carga de clases cuando existe la misma clase en diferentes aplicaciones en el mismo servidor?
introducción a android studio incluye proyectos reales y el código fuente pdf (3)
La mayoría del uso del servidor de aplicaciones más específico a lo largo de una ruta tiene prioridad . Si tiene varias bibliotecas que hacen lo mismo, debe considerar ponerlas dentro del servidor de aplicaciones lib (fe: TOMCAT_HOME / lib)
Tengo varias aplicaciones web ejecutándose en un servidor de aplicaciones y cada archivo WAR de la aplicación web contiene una copia del mismo archivo jar.
¿Esto significa que una clase en ese archivo jar se cargará varias veces en la JVM, una vez por cada archivo WAR en que exista? A continuación, si tengo un método estático sincronizado en dicha clase, solo está sincronizado entre hilos dentro de la aplicación web, existe pero no está sincronizado con el mismo método en la misma clase en un archivo jar diferente en un archivo diferente. ¿Archivo WAR? (Espero que la pregunta tenga sentido, aclarará si es necesario).
Si este es el caso, supongo que la mejor solución es eliminar el archivo jar de cada archivo WAR y desplegarlo en una carpeta classpath compartida en el servidor.
Los servidores de aplicaciones Java EE suelen utilizar varios cargadores de clases para aislar aplicaciones entre sí y permiten implementar nuevas versiones de una aplicación sin afectar a otras aplicaciones.
Obtiene patrones tales como varios archivos WAR y un archivo EJB en un EAR con una jerarquía de cargadores de clases, cada WAR tiene su propio.
Esto lleva a una duplicación como usted describe, pero esto no es necesariamente algo malo. Significa que incluso puede tener diferentes versiones de los mismos JAR desplegados al mismo tiempo, y que en realidad pueden ser beneficiosos, lo que permite la migración incremental a nuevas versiones.
Algunos servidores de aplicaciones (WebSphere para exmaple) tienen soporte explícito para un concepto de biblioteca compartida, y yo uso eso.
Tenga cuidado de simplemente colocar JAR en classpaths arbitrarios, usted corre el riesgo de desestabilizar el servidor de la aplicación.
Un cargador de clases Java normalmente funciona buscando clases en uno o más lugares en una secuencia fija. Por ejemplo, el cargador de clases que carga su aplicación cuando la ejecuta desde la línea de comando se ve primero en el archivo rt.jar
(y otros en el bootclasspath), y luego en los directorios y archivos JAR especificados por su classpath.
Una carga de clase de webapp es similar en principio, pero un poco más complicada en la práctica. Para una aplicación web particular, el cargador de clases de una aplicación busca clases en el siguiente orden. Por ejemplo, Tomcat 6 busca clases en este orden:
- Clases de Bootstrap de su JVM
- Clases del cargador de clases del sistema (descritas here )
- / WEB-INF / clases de la aplicación web
- /WEB-INF/lib/*.jar de la aplicación web
- $ CATALINA_HOME / lib
- $ CATALINA_HOME / lib / *. Jar
Por supuesto, una vez que el cargador de clases ha encontrado la clase que está buscando, no busca más. Por lo tanto, las clases con el mismo nombre más adelante en el pedido no se cargarán.
La complicación es que el contenedor web tiene un cargador de clases para cada aplicación web, y estos cargadores de clases delegan a otros cargadores de clases que administran las clases comunes. En la práctica, esto significa que algunas clases solo se cargarán una vez para todo el contenedor (por ejemplo, 1. y 2.) y otras pueden ser cargadas varias veces por diferentes clasificadores.
(Cuando una clase se carga más de una vez, da como resultado objetos de clase distintos y estáticas de clase distintas. Las versiones de la clase son de tipos diferentes en lo que se refiere a la JVM y no puede encasillar de una versión a otra).
Finalmente, Tomcat se puede configurar para permitir que las webapps individuales se "carguen en caliente". Esto implica detener una aplicación web, crear un nuevo cargador de clases y reiniciarla.
SEGUIR
Entonces ... ¿sincronizar un método estático no protegerá el acceso a un recurso compartido donde la clase se ha cargado varias veces?
Depende de los detalles, pero probablemente no lo haga. (O para ver si de otra manera, si una clase realmente se ha cargado varias veces, entonces un método static
de cada "carga" de la clase accederá a un conjunto diferente de campos static
).
Si realmente desea que una instancia de clase de aplicación singleton sea compartida por varias aplicaciones web en el mismo contenedor, es más simple si coloca la clase en $CATALINA_HOME/lib
o su equivalente. Pero también debe preguntarse si este es un buen diseño del sistema. Considere combinar webapps, o usar el reenvío de solicitudes, etc., en lugar de una estructura de datos compartida. El patrón singleton tiende a ser problemático en webapps, y este sabor es aún más.