Esta es una página de descripción general; visite hotswapagent.org para obtener más información.
Redefinición de recursos y clases de tiempo de ejecución ilimitado de Java.
El objetivo principal de este proyecto era eliminar la necesidad del ciclo de desarrollo tradicional "cambiar código -> reiniciar y esperar... -> verificar". Con el tiempo, este concepto ha evolucionado hasta convertirse en un nuevo paradigma dentro del ecosistema Java, que permite el desarrollo de software en tiempo real dentro de una aplicación en ejecución. Este enfoque es incluso factible en entornos restringidos, como los contenedores Docker.
Si es usuario de IntelliJ, puede simplificar la configuración de HA y DCEVM utilizando el complemento IntelliJ HotSwapHelper.
Descargar e instalar:
Para Java 17/21: descargue la última versión de JBR17 o JBR21. Dado que estas versiones no incluyen un Hotswap Agent integrado, deberá copiar manualmente hotswap-agent.jar
a la carpeta lib/hotswap
. Puede encontrar el último agente Hotswap aquí. Asegúrese de que el archivo en la carpeta lib/hotswap
se llame hotswap-agent.jar
sin ningún número de versión en el nombre del archivo.
Para Java 11: utilice TravaJDK, que tiene un HotswapAgent integrado, e instálelo como JDK alternativo. Alternativamente, TravaJDK incluye un HotswapAgent integrado.
Para Java 8: utilice jdk8-dcevm junto con HotswapAgent.
Modos HotswapAgent:
A partir de dcevm-11.0.9
, HotswapAgent está deshabilitado de forma predeterminada. Puede habilitar la compatibilidad con HotswapAgent utilizando las opciones de JVM en uno de tres modos:
El modo HotswapAgent=core
funciona sin complementos adicionales, excepto los complementos principales de JVM, lo que resulta en un rendimiento más rápido debido a la reducción de las tareas de escaneo y copia de clases. Para utilizar complementos adicionales, debe configurarlos como dependencias de Maven en su archivo pom.xml
. Por otro lado, el modo HotswapAgent=fatjar
incluye todos los complementos de forma predeterminada, lo que puede ralentizar ligeramente el inicio de la aplicación.
-XX:HotswapAgent=fatjar
activa el fatjar HotswapAgent interno.
-XX:HotswapAgent=core
activa el núcleo interno HotswapAgent.
-XX:HotswapAgent=external
configura el soporte de JVM para HotswapAgent y permite al usuario proporcionar un hotswap-agent.jar
externo usando la opción -javaagent:
.
3. Lanzamiento:
Java17/21: inicie su aplicación con las opciones -XX:+AllowEnhancedClassRedefinition -XX:HotswapAgent=fatjar
para activar el hotswap avanzado (dcevm) y usar la versión fatjar del Hotswap Agent. Como alternativa, se pueden utilizar modos core
o external
en lugar de fatjar
.
Java11: inicie su aplicación con las opciones -XX:HotswapAgent=fatjar
para usar la versión fatjar de Hotswap Agent.
Java8: inicie su aplicación con las opciones -XXaltjvm=dcevm -javaagent:hotswap-agent.jar
para obtener una configuración básica. Opcionalmente, puede agregar hotswap-agent.properties
a su aplicación para configurar complementos y el comportamiento del agente.
3.Ejecute su aplicación:
Inicie la aplicación en modo de depuración, verifique que el agente y los complementos estén inicializados correctamente:
HOTSWAP AGENT: 9:49:29.548 INFO (org.hotswap.agent.HotswapAgent) - Loading Hotswap agent - unlimited runtime class redefinition. HOTSWAP AGENT: 9:49:29.725 INFO (org.hotswap.agent.config.PluginRegistry) - Discovered plugins: [org.hotswap.agent.plugin.hotswapper.HotswapperPlugin, org.hotswap.agent.plugin.jvm.AnonymousClassPatchPlugin, org.hotswap.agent.plugin.hibernate.HibernatePlugin, org.hotswap.agent.plugin.spring.SpringPlugin, org.hotswap.agent.plugin.jetty.JettyPlugin, org.hotswap.agent.plugin.tomcat.TomcatPlugin, org.hotswap.agent.plugin.zk.ZkPlugin, org.hotswap.agent.plugin.logback.LogbackPlugin] ... HOTSWAP AGENT: 9:49:38.700 INFO (org.hotswap.agent.plugin.spring.SpringPlugin) - Spring plugin initialized - Spring core version '3.2.3.RELEASE'
4.Verificar redefinición
Guarde un recurso modificado y/o use la función HotSwap de su IDE para recargar los cambios
Cada marco de aplicación (Spring, Hibernate, Logback, ...) necesita un mecanismo de recarga especial para mantenerse actualizado después de la redefinición de la clase (por ejemplo, recarga de la configuración de Hibernate después de que se introduce una nueva clase de entidad). El agente Hotswap funciona como un sistema de complementos y se envía preconfigurado con todos los complementos principales del marco. Es fácil escribir su complemento personalizado incluso como parte de su aplicación.
Este proyecto es muy complejo debido a la gran cantidad de marcos compatibles y varias versiones. La aportación comunitaria es obligatoria para mantenerlo vivo. Puede comenzar creando un complemento dentro de su aplicación o escribiendo un ejemplo/prueba de integración. Siempre es necesario mejorar la documentación :-). ¡Gracias por cualquier ayuda!
Java Hotswap mejorado: cambiar el cuerpo del método, agregar/cambiar el nombre de un método, campo,... La única operación no admitida es cambiar la superclase.
Puede utilizar Java Hotswap estándar desde IDE en modo de depuración para recargar la clase modificada
o establezca la propiedad autoHotswap -XXaltjvm=dcevm -javaagent:PATH_TO_AGENThotswap-agent.jar=autoHotswap=true
para recargar las clases modificadas después de la compilación. Esta configuración permite incluso recargar en un sistema de producción sin reiniciar.
Configuración automática: todas las clases y recursos locales conocidos por la aplicación Java en ejecución se descubren y supervisan automáticamente para la recarga (todos los archivos en el sistema de archivos local, no dentro de ningún archivo JAR).
Classpath adicional: ¿necesita cambiar una clase de tiempo de ejecución dentro del JAR dependiente? Utilice la propiedad extraClasspath para agregar cualquier directorio como classpath para buscar archivos de clase.
Recargar recurso después de un cambio: el servidor de aplicaciones suele recargar los recursos del directorio de aplicaciones web. Pero ¿qué pasa con otros recursos como src/main/resources? Utilice la propiedad watchResources para agregar cualquier directorio y observar un cambio de recurso.
Compatibilidad con marcos: a través del sistema de complementos, se admiten muchos marcos. Se pueden agregar fácilmente nuevos complementos.
Rápido: hasta que se inicializa el complemento, no consume ningún recurso ni ralentiza la aplicación (consulte sobrecarga de tiempo de ejecución para obtener más información).
Si tiene algún problema o pregunta, pregunte en el foro HotswapAgent.
Este proyecto es similar a JRebel. Las principales diferencias son:
¡HotswapAgent (DCEVM) es compatible con Java8, Java11 y Java17!
HotswapAgent no necesita ninguna configuración adicional para la configuración básica del proyecto.
JRebel es actualmente más maduro y contiene más complementos.
JRebel no es de código abierto ni gratuito.
JRebel modifica el código de bytes de todas las clases al recargar. Necesita un complemento IDE especial para solucionar la depuración.
HotswapAgent extraClasspath es similar a la configuración de JRebel
HotswapAgent agrega la configuración de watchResources
Consulte el proyecto GitHub HotswapAgentExamples. El propósito de una aplicación de ejemplo es:
pruebas de integración automatizadas complejas (verifique varias configuraciones antes de un lanzamiento, consulte el script run-tests.sh
)
para verificar el uso del complemento en el "mundo real" durante el desarrollo del complemento (es decir, dentro de un contenedor)
para proporcionar una solución funcional para configuraciones de aplicaciones típicas
Sandbox para simular problemas para configuraciones nuevas o existentes.
Siéntase libre de bifurcar/bifurcar y crear una aplicación para su configuración (funcional, pero lo más simple posible). Las configuraciones generales se fusionarán en el maestro.
No se necesita ninguno :) ¡De verdad! Todos los cambios son transparentes y todo lo que necesita hacer es descargar parche+agente y configurar su aplicación/servidor de aplicaciones. Debido a que utilizamos el comportamiento estándar de intercambio en caliente de Java, su IDE funcionará como se espera. Sin embargo, trabajamos en complementos IDE para ayudar con la descarga y la configuración.
Algunos complementos ya están disponibles:
Agregue dos acciones al lado del botón "Depurar" en intellij, Ejecutar con hotswap, Depurar con hotswap.
Al hacer clic en la acción, se configurarán los parámetros de VM por usted, no es necesario configurar los parámetros de VM manualmente.
Código fuente y documentación: https://github.com/gejun123456/HotSwapHelper.
La configuración básica está configurada para recargar clases y recursos desde el classpath conocido por la aplicación en ejecución (cargador de clases). Si necesita una configuración diferente, agregue el archivo hotswap-agent.properties a la raíz de classpath (por ejemplo, src/main/resources/hotswap-agent.properties
).
La documentación detallada de las propiedades disponibles y los valores predeterminados se puede encontrar en el archivo de propiedades del agente.
La sintaxis completa de las opciones de la línea de comando es:
-javaagent:[yourpath/]hotswap-agent.jar=[option1]=[value1],[option2]=[value2]
El agente Hotswap acepta las siguientes opciones:
autoHotswap=true: observe todos los archivos .class en busca de cambios e intercambie automáticamente la clase en la aplicación en ejecución (en lugar de ejecutar Hotswap desde su sesión de depuración de IDE)
enablePlugin=[pluginName] - deshabilita un complemento. Tenga en cuenta que esto prohibirá por completo la carga del complemento (a diferencia de la opción deshabilitarPlugin en hotswap-agent.properties, que solo deshabilitará el complemento para un cargador de clases. Puede repetir esta opción para cada complemento que desee deshabilitar.
Agregue la opción vm -Dhotswapagent.disablePlugin=Spring,SpringBoot para deshabilitar complementos, funciona igual que la opción de agente enablePlugin en la sección anterior.
El agente Hotswap realiza el trabajo de recargar recursos y configuración del marco (Spring, Hibernate, ...), pero depende del mecanismo estándar de intercambio en caliente de Java para recargar clases. El hotswap estándar de Java sólo permite cambiar el cuerpo del método, lo que lo hace prácticamente inutilizable. DCEVM es un parche JVM (Hotspot) que permite casi cualquier cambio de clase estructural en hotswap (con excepción de un cambio de jerarquía). Aunque el agente hotswap funciona incluso con Java estándar, recomendamos usar DCEVM (y todos los tutoriales usan DCEVM como JVM de destino).
El agente Hotswap es un contenedor de complementos con administrador de complementos, registro de complementos y varios servicios de agente (por ejemplo, para observar cambios de clase/recurso). Ayuda con tareas comunes y problemas de carga de clases. Escanea el classpath en busca de clases anotadas con la anotación @Plugin, inyecta servicios de agente y registra ganchos de recarga. La modificación del código de bytes en tiempo de ejecución la proporciona la biblioteca javaasist.
Los complementos administrados por Hotswap Agent generalmente se centran en un marco específico. Por ejemplo, el complemento Spring utiliza servicios HA para:
Modifique las clases raíz de Spring para obtener contextos de Spring y la ruta de escaneo registrada
Esté atento a cualquier cambio de recursos en una ruta de escaneo
Esté atento a un intercambio en caliente de un archivo de clase dentro de un paquete de ruta de escaneo
Recargar la definición de bean después de un cambio
... y muchos otros
CXF-JAXRS (3.x): redefine el recurso JAXRS después de la redefinición de la clase de recurso, reinyecta la instancia si está integrada con Spring y CDI (Weld/OWB).
Deltaspike (1.x,2.x): mensajes, ViewConfig, repositorio, recarga de proxy. Reinyección de beans CDI con alcance Deltaspike.
ELResolver (2.x-5.x) (JuelEL, Appache Commons EL, Oracle EL 3.0): borre la caché de ELResolver al cambiar de clase. Admite hotswap para #{...} expresiones.
FreeMarker: borra la caché de introspección de clases de los beans Apache Freemarker al cambiar la definición de clase.
Hibernar (3.x-6.x): recargar la configuración de Hibernación después de crear/cambiar la entidad.
iBatis - Recarga de configuración de iBatis.
IDEA: soporte para el desarrollo de IntelliJ IDEA en IDEA
Jackson: borra los cachés internos de Jackson cuando se redefine la clase.
Jersey1: recarga el contenedor Jersey1 después de la definición o redefinición de la clase de proveedor o recurso raíz.
Jersey2: recarga el contenedor Jersey2 después de la definición o redefinición de la clase de proveedor o recurso raíz.
Inicio de sesión: recarga de la configuración del inicio de sesión.
Log4j2: recarga de configuración de Log4j2.
Mojarra (2.x): soporte para cambios en el paquete de recursos de la aplicación (archivo de propiedades). Soporte para reinyección/recarga de beans ViewScoped.
MyBatis (5.3): recarga la configuración después de cambios en el archivo del mapeador
MyFaces (2.x-4.x): compatibilidad con cambios en el paquete de recursos de la aplicación (archivos de propiedades). Soporte para reinyección/recarga de beans ViewScoped.
OmniFaces: soporte para reinyección/recarga de beans ViewScoped.
OpenWebBeans - (CDI) (1.x-4.x): recarga la definición de clase de bean después de la definición/cambio de clase. Los beans se pueden recargar según la estrategia definida en el archivo de propiedades.
OsgiEquinox: soporte Hotswap para el complemento Eclipse o el desarrollo de la plataforma Eclipse.
RestEasy (2.x, 3.x): limpiezas y redefiniciones de clases de registros.
Spring (3.2.x+, 4.x, 5.x): recarga la configuración de Spring después de la definición/cambio de clase.
Spring Boot (1.5.x+, 2.0.x): recarga dinámica de archivos de configuración de Spring Boot en tiempo real.
Vaadin (23.x, 24.x): actualiza rutas, modelos de plantilla y, en la práctica, cualquier cosa sobre la marcha.
WebObjects: borre la codificación de valores clave, los componentes, las acciones y las cachés de validación después del cambio de clase.
Weld (CDI) (2.x-5.x): recarga la definición de clase de bean después de la definición/cambio de clase. Los beans se pueden recargar según la estrategia definida en el archivo de propiedades.
Wicket: borre los cachés de wicket si se cambian los archivos de propiedades
WildFlyELResolver: borre BeanELResolver después de cualquier redefinición de clase.
ZK (5x-7x) - Marco ZK (http://www.zkoss.org/). Cambie los valores predeterminados de las propiedades de la biblioteca para deshabilitar los cachés, mantiene el caché de etiquetas y el caché de resolución de beans.
JBossModules: agregue una ruta de clases adicional al cargador de clases de módulos de JBoss. (Mosca salvaje)
Jetty: agregue una ruta de clases adicional al cargador de clases de la aplicación. Deben ser compatibles todas las versiones que admitan WebAppContext.getExtraClasspath.
Tomcat (7.x,8.x,9.x,10.x) configura Apache Tomcat con la propiedad extraClasspath y webApp. También es compatible con GlassFish, Payara y Tomee7.
Resaca: agregue classpath, watchResources y webappDir adicionales al administrador de recursos de la resaca.
Weblogic: agregue una ruta de clase adicional al cargador de clases de la aplicación.
AnonymousClassPatch: intercambia nombres de clases internas anónimas para evitar cambios no compatibles.
ClassInit: inicializa nuevos miembros estáticos/valores de enumeración después de la redefinición de clase/enum y mantiene los valores estáticos supervivientes. (Solución de limitación conocida de DCEVM)
Hotswapper: esté atento a cualquier cambio de archivo de clase y recárguelo (intercambie en caliente) sobre la marcha a través de Java Platform Debugger Architecture (JPDA)
Proxy (compatible con com.sun.proxy, CGlib): redefine las clases de proxy que implementan o amplían interfaces o clases modificadas.
Encuentre documentación detallada de cada complemento en el archivo README.md principal del proyecto del complemento.
Depende de cuántos frameworks uses y qué cachés estén deshabilitados. Medidas de ejemplo para una aplicación empresarial grande del mundo real basada en Spring + Hibernate, ejecutada en Jetty.
Setup | Startup time -----------------------------|------------- Run (plain Java) | 23s Debug (plain Java) | 24s Debug (plain DCEVM) | 28s Agent - disabled all plugins | 31s Agent - all plugins | 35s
Puede escribir un complemento directamente como parte de su aplicación. Establezca pluginPackages=your.plugin.package
dentro de su configuración hotswap-agent.properties
para descubrir clases anotadas @Plugin
. También necesitará la dependencia JAR del agente para compilar, pero tenga cuidado de NO agregar el JAR a su aplicación; debe cargarse únicamente como agente java. Dependencia de Maven:
org.hotswapagent HotswapAgent ${project.version} provided
Consulte EjemploPlugin (parte de TestApplication) para ver un complemento simple comentado. Lea el archivo Léame del agente para comprender los conceptos del agente. Consulte el código fuente de los complementos existentes para ver más ejemplos.
Inicie el script run-tests.sh
en el directorio principal. Actualmente, debe configurar el directorio de ubicación JAVA_HOME manualmente. Se debe verificar al menos Java 11 con DCEVM antes de su lanzamiento. Todas las pruebas automáticas están configuradas para fallar en todo el script en caso de que falle una sola prueba.
Vaya al directorio que representa la raíz del repositorio. En caso de que DCEVM se llame dcevm
mvn release:prepare mvn release:perform
Agente de hotswap:
Jiri Bubnik - coordinador del proyecto, implementación inicial
Alexandros Papadakis: control de versiones de Maven, Weld, JSF, Hibernate3, RestEasy, complementos WildFly
Erki Ehtla: complemento Spring, complemento Proxy
Vladimir Dvorak - ELResolver, OsgiEquinox, Weld, Owb, Deltaspike, Jvm, Jdk, JBossModules, ClassInit, JSF, Mybatis
Sergey Lysenko - Complemento de soldadura
Samuel Pelletier - Complemento WebObjects
Jan Tecl - diseño web
@liuzhengyang - complemento jackson
Lukasz Warzecha - Complemento Log4j2
@muwaiwai - complemento iBatis
Thomas Heigl - Complemento de wicket
AJ Banck - Complemento FreeMarker
Sinan Yumak - Mojarra, complementos MyFaces
Smallfour - Complemento Mybatis
@cvictory - Complemento Spring, complemento Spring Boot
@homejim - Complemento MyBatis, complemento MyBatisPlus
DCEVM:
Thomas Würthinger: implementación inicial.
Ivan Dubrov - ex coordinador de proyectos, actualización a Java7+Java8, parches, sistema de compilación (Gradle)
Kerstin Breitender - colaboradora.
Christoph Wimberger - colaborador.
Vladimir Dvorak - migración java9,java11,jbr17,jbr21, colaborador
Jiri Bubnik - migración java9,java11