2010-12-29 21 views
52

Asumamos que tenemos un programa trivial Java que consta de una sola clase:Cambiar un método en tiempo de ejecución a través de un mecanismo de intercambio en caliente

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 que se compila y ejecuta, la salida será la siguiente:

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 de 2

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

...

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

Por lo tanto, 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 a Erlang's hot code swapping donde puedo hacer esto: programa original

  1. plazo
  2. versión modificada de escritura
  3. usando un programa de línea de comando, conéctese a JVM en ejecución y reemplace el método existente

de manera que, durante el tiempo de ejecución, esto sucederá:

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

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

Hoy en día es una aún mejor día con un número 15002

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

...

Supongamos que el programa 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 programa Hello world style.

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

+3

¿Puede explicar por qué no puede usar el Patrón de estrategia (por ejemplo, un objeto variable que implementa la funcionalidad variable requerida)? Los métodos de intercambio suenan complicados para lograr lo que desea. – ivy

+0

@ivy: Podría usar eso, por supuesto, pero me pregunto si es posible hacer lo que describí en mi pregunta. Puede pensarlo como una pregunta "teórica" ​​de alguna manera. – darioo

+0

@ivy el mecanismo está ahí para actualizar un servicio en ejecución, no para seleccionar entre un conjunto de implementaciones conocidas. –

Respuesta

35

Usted puede utilizar el código abierto HotSpot VM o el plug-in comercial JRebel IDE para lograr fácilmente su objetivo (Ver tabla de comparación here).

+0

es esto robusto y adecuado para entornos de producción? Al igual que en la actualización en caliente a los servicios en ejecución sin tiempo de inactividad? ¿O es realmente solo una forma de acortar un ciclo de edición/compilación/ejecución en dev? – Kevin

+0

No, no es adecuado para la producción – IcedDante

3

Usted puede hacer esto a través de la (plataforma Java Depurador de Arquitectura) de la interfaz JPDA: http://download.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap

No es automático según sea el caso Erlang - la JVM no supervisa la ruta de clase para los cambios en los archivos de clase y vuelve a cargar y se vuelve a vincular si se modifican, por razones bastante obvias (Java se diseñó para la implementación web; no se desea consultar los cambios en una URL http).

+0

Voy a probar JPDA un día. Lo que tenía en mente era inverso.JVM no supervisa los cambios en el archivo de clase, pero le está entregando directamente a la JVM en ejecución una versión "nueva" de una clase. – darioo

14

Puede hacerlo a través de cargadores de clase. 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 un great explanation of creating dynamic code in java. No solo explica la carga sino también la compilación de la fuente sobre la marcha. Debe poder aplicar los conceptos cubiertos a cualquier estrategia de recarga de código que desee utilizar.

9

He usado este hotswap ant task 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 una secuencia de comandos que el código de hotswaps cambia 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.

+0

Plus 1 porque menciona JPDA, que es la interfaz JVM real utilizada por las herramientas. Ahora solo quiero ver un ejemplo mínimo ejecutable :-) –

2

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

2

Puede usar el patrón de diseño de Estrategia, por lo que tiene un objeto para manipular en lugar de un método y un protocolo para comunicarse con el programa para indicarle que use un nombre de clase dado como clase del objeto de Estrategia.

4

Un puesto un poco pasada, pero es de esperar que alguien se encuentra este útil:

he encontrado el relativamente nuevo Hotswap Agent está bien documentado y rico en funciones (y lo mejor de todo, open source).

Cuestiones relacionadas