Cambiar un método en tiempo de ejecución a través de un mecanismo de intercambio en caliente

Supongamos que tenemos un progtwig trivial de Java que consiste en una sola clase:

public class HelloWorld { private static void replacable(int i) { System.out.println("Today is a nice day with a number " + i); } public static void main(String[] args) throws Exception { for(int i = 0; i < 100000; ++i) { replacable(i); Thread.sleep(500); } } 

Después de comstackrse y ejecutarse, la salida será esta:

Hoy es un buen día con un número 0

Hoy es un buen día con un número 1

Hoy es un buen día con un número 2

Hoy es un buen día con un número 3

Mi pregunta: ¿existe (o hay en el horizonte) alguna forma de intercambiar el método replacable en el tiempo de ejecución? ¿Algo como escribir otra versión de HelloWorld con una nueva versión de replacable , comstackndo y luego la versión anterior en una JVM ya en ejecución?

Entonces, si escribo la nueva versión de esta manera:

 private static void replacable(int i) { System.out.println("Today is an even nicer day with a number " + i); } 

¿Hay algo similar al intercambio de código caliente de Erlang en el que puedo hacer esto?

  1. ejecutar el progtwig original
  2. escribir versión modificada
  3. usando un progtwig de línea de comando, conéctese a ejecutar JVM y reemplace el método existente

para que, durante el tiempo de ejecución, esto suceda:

Hoy es un buen día con un número 15000

Hoy es un buen día con un número 15001

Hoy es un día aún más agradable con un número 15002

Hoy es un día aún más agradable con un número 15003

Supongamos que el progtwig anterior es independiente, se ejecuta en un entorno Java SE estándar, no hay nada más en classpath, por lo que es casi un progtwig Hello world style.

Nota: Sé que existen tecnologías como la manipulación de códigos de bytes ( cglib ), aspectJ , jRebel , JMX , hotswapping de métodos en Java EE, etc., pero no son en lo que estoy pensando. Piensa en Erlang.

Puede utilizar la máquina virtual de HotSpot de código abierto o el complemento comercial IDE de JRebel para alcanzar fácilmente su objective (consulte la tabla de comparación aquí ).

Puedes hacerlo a través de cargadores de clases. Por ejemplo, si está familiarizado con contenedores Servlet como tomcat que vuelven a cargar páginas a medida que las modifica en el desarrollo. Aquí hay una gran explicación para crear código dynamic en java . No solo explica la carga sino también la comstackción de la fuente sobre la marcha. Debe poder aplicar los conceptos cubiertos a cualquier estrategia de recarga de código que desee utilizar.

He usado esta tarea de hotswap en muchos proyectos. La aplicación Java de destino se puede iniciar a través de Ant, Eclipse, un símbolo del sistema o cualquier otro medio, siempre que se lance en modo de depuración con el puerto apropiado abierto. La página vinculada proporciona instrucciones sobre cómo hacer esto a través de Ant.

Cualquier número de clases puede ser enmascarado siempre que los cambios no sean estructurales. Los cambios en el cuerpo del método generalmente se intercambian con facilidad. El código puede ser enmascarado ejecutando un script ant a través de un shell o Eclipse.

En el trabajo, utilizo un script que cambia el código de hotswaps automáticamente al comparar las marcas de tiempo en los archivos de clase. Esto es similar a la muestra en la página del proyecto que muestra un ejemplo simple que solo hotswaps cambió las clases.

Nota adicional: Esto utiliza el JPDA .

Una publicación un poco antigua, pero con suerte alguien lo encontrará útil:

Descubrí que el relativamente nuevo agente de Hotswap está bien documentado y tiene muchas funciones (y, lo mejor de todo, de código abierto ).

Puede hacerlo a través de la interfaz JPDA (Java Platform Debugger Architecture): http://download.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap

No es automático como el caso de Erlang: la JVM no supervisa la ruta de la clase para cambios en los archivos de la clase y luego vuelve a cargarlos y volver a vincularlos si se modifican, por razones bastante obvias (Java se diseñó para la implementación web; no se desea sondear una http URL para cambios).

¿Qué hay de OSGi? El intercambio en caliente está “incorporado” a la especificación, creo que esta sería una posible solución también.

Podría usar el patrón de diseño de Estrategia, de modo que tenga un objeto para manipular en lugar de un método, y un protocolo para comunicarse con el progtwig para indicarle que use un nombre de clase dado como la clase del objeto de Estrategia.

    Intereting Posts