2010-10-23 9 views
68

Me gustaría implementar una aplicación java (aplicación de servidor) que pueda descargar una nueva versión (archivo .jar) desde una url determinada, y luego actualizarse en tiempo de ejecución.¿Cómo puedo escribir una aplicación Java que pueda actualizarse en tiempo de ejecución?

¿Cuál es la mejor manera de hacer esto y es posible?

Supongo que la aplicación puede descargar un nuevo archivo .jar e iniciarlo. Pero, ¿cómo debo hacer el traspaso, p. saber cuándo se inicia la nueva aplicación y luego salir. ¿O hay una mejor manera de hacer esto?

+4

¿Has mirado Java Web Start? Sin embargo, no se actualiza en el tiempo de ejecución, creo, (se requiere reiniciar), para eso es probable que tengas que mirar OSGi. – Thilo

+0

@Thilo: creo que sería fácil descargar un archivo de una url determinada y luego iniciarlo con un comando de Linux desde el archivo jar en ejecución. – Jonas

+1

El diseño de la API de Java WebStart hace que sea imposible actualizar mientras se ejecuta. Desafortunadamente. –

Respuesta

46

La estructura básica de una solución es la siguiente:

  • No es un bucle principal responsable de cargar varias veces la última versión de la aplicación (si es necesario) y el lanzamiento de la misma.

  • La aplicación hace su trabajo, pero comprueba periódicamente la URL de descarga. Si detecta una nueva versión, vuelve al lanzador.

Existen varias formas de implementarlo. Por ejemplo:

  • El lanzador podría ser un guión envoltorio o aplicación binaria que se inicia una nueva JVM para ejecutar la aplicación desde un archivo JAR que es reemplazado.

  • El iniciador podría ser una aplicación Java que crea un cargador de clases para el nuevo JAR, carga una clase de punto de entrada y llama a algún método sobre él. Si lo haces de esta manera, tienes que estar atento a las fugas de almacenamiento del cargador de clases, pero eso no es difícil. (. Sólo tiene que asegurarse de que no hay objetos con clases cargadas desde el JAR son accesibles después de que vuelve a lanzar)

Las ventajas del enfoque de la envoltura externa son:

  • que sólo necesita un JAR ,
  • se puede sustituir toda la aplicación Java,
  • todos los hilos secundarios creados por la aplicación, etc va a desaparecer sin lógica especial de cierre, y
  • también se puede tratar con la recuperación de aquí para allá aplicación se bloquea m, etc.

El segundo enfoque requiere dos tarros, pero tiene las siguientes ventajas:

  • la solución es puro Java y portátil,
  • el cambio será más rápido, y
  • puede retener más fácilmente el estado durante el reinicio (problemas de fuga del módulo).

La "mejor" manera depende de sus requisitos específicos.

También hay que señalar que:

  • hay riesgos de seguridad con la actualización automática. En general, si el servidor que proporciona las actualizaciones se ve comprometido, o si los mecanismos para proporcionar las actualizaciones son susceptibles de ataque, la actualización automática puede llevar a un compromiso del cliente (s).

  • Aplicar una actualización a un cliente que cause daños al cliente podría tener riesgos legales y riesgos para la reputación de su negocio.


Si se puede encontrar una manera de evitar reinventar la rueda, eso sería bueno. Vea las otras respuestas para sugerencias.

2

Esto no es necesariamente el mejor forma, pero podría funcionar para usted.

Puede escribir una aplicación de arranque (como el lanzador de World of Warcraft, si jugó WoW). Ese bootstrap es responsable de buscar actualizaciones.

  • Si hay una actualización disponible, se ofrecen al usuario, manejar la descarga, instalación, etc.
  • Si la solicitud es hasta la fecha, que permitirá al usuario para iniciar la aplicación
  • Opcionalmente, puede permitir al usuario iniciar la aplicación, aunque no es hasta la fecha

de esta manera usted no tiene que preocuparse de forzar la salida de su aplicación.

Si su aplicación está basada en la web, y si es importante que tengan un cliente actualizado, entonces también puede hacer comprobaciones de versión mientras se ejecuta la aplicación. Puede hacerlo a intervalos, mientras realiza una comunicación normal con el servidor (algunas o todas las llamadas) o ambas.

Para un producto en el que trabajé recientemente, hicimos comprobaciones de versión tras el lanzamiento (sin una aplicación de corrección de arranque, pero antes de que apareciera la ventana principal) y durante las llamadas al servidor. Cuando el cliente estaba desactualizado, confiamos en que el usuario salga manualmente, pero prohibimos cualquier acción contra el servidor.

Tenga en cuenta que no sé si Java puede invocar el código de la interfaz de usuario antes de abrir la ventana principal. Estábamos usando C#/WPF.

+0

Gracias , esa es una buena manera de hacerlo. Pero es una aplicación de servidor, por lo que no hay ningún usuario que pueda tomar alguna medida. Y preferiría que fuera solo un archivo jar único, por lo que el usuario easyli puede descargar un solo contenedor y comenzarlo al principio, pero después de eso me gustaría no tener interacciones con el usuario. – Jonas

+0

Cuando dices "aplicación de servidor", ¿quieres decir que es una aplicación que se ejecuta directamente en el servidor, mientras estás conectado? –

+0

@Jonas: No entiendo mucho acerca de cómo funcionan los archivos .jar, por lo que no puedo ser de mucha utilidad allí. Puedo entender si prefieres una respuesta específica para Java. Con suerte, esto le da algo de que pensar, al menos :) –

10

He escrito una aplicación Java que puede cargar complementos en tiempo de ejecución y comenzar a usarlos inmediatamente, inspirados en un mecanismo similar en jEdit. jEdit es de código abierto, por lo que tiene la opción de ver cómo funciona.

La solución utiliza un ClassLoader personalizado para cargar archivos desde el contenedor. Una vez que se carguen, puede invocar algún método del nuevo jar que actuará como su método main. Luego, la parte difícil es asegurarse de que se deshace de todas las referencias al código anterior para que pueda ser basura recolectada. No soy un experto en esa parte, lo he hecho funcionar, pero no fue fácil.

+0

No sé sobre Java, pero en C#, puede usar AppDomains para descargar código explícitamente. Tal vez hay un concepto similar en Java. –

+0

+1. Buena sugerencia –

+1

Gracias, este parece ser el camino a seguir. Hay un ejemplo de un 'NetworkClassLoader' en JavaDoc para [ClassLoader] (http://download.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) – Jonas

5
  1. Primera forma: utilizar tomcat y desplegar instalaciones.
  2. Segunda manera: dividir la aplicación en dos partes (funcionales y de actualización) y dejar que la parte de función de reemplazo de parte de actualización.
  3. Tercera forma: en su aplicación de servidor solo descarga la nueva versión, la versión anterior libera el puerto vinculado, la versión anterior ejecuta la nueva versión (inicia el proceso) y la versión anterior envía una solicitud al puerto de la aplicación. , la versión anterior finaliza y la nueva versión elimina la versión anterior. De esta manera: alt text
+0

Su segunda forma parece ser un diseño interesante. – Jonas

2

Si se construye la aplicación utilizando Equinox plugins, puede utilizar la P2 Provisioning System para obtener una solución lista para usar a este problema. Esto requerirá que el servidor se reinicie después de una actualización.

7

Este es un problema conocido y recomiendo que no reinvente una rueda: no escriba su propio truco, simplemente use lo que otras personas ya han hecho.

dos situaciones que deben tener en cuenta:

  1. aplicación tiene que ser auto-actualizable y seguir funcionando incluso durante la actualización (aplicación de servidor, aplicaciones incrustadas). Vaya con OSGi: Bundles o Equinox p2.

  2. La aplicación es una aplicación de escritorio y tiene un instalador. Hay muchos instaladores con la opción de actualización. Compruebe installers list.

28

Actualmente estoy desarrollando un JAVA Linux Daemon y también tuve la necesidad de implementar un mecanismo de actualización automática. Quería limitar mi aplicación a un archivo jar, y se me ocurrió una solución simple:

Embale la aplicación de actualización en la actualización misma.

Aplicación: Cuando la aplicación detecta una versión más reciente hace lo siguiente:

  1. descarga de la actualización (fichero Zip)
  2. Extracto de Aplicación y ApplicationUpdater (todos en el archivo zip)
  3. Ejecute el actualizador

ApplicationUpdater: Cuando el programa de actualización se ejecuta hace lo siguiente:

  1. detener la aplicación (en mi caso a través de un daemon init.d)
  2. Copia el archivo jar descargado para sobrescribir aplicación actual
  3. inicio del Aplicación
  4. Limpieza.

Espero que ayude a alguien.

0

Veo un problema de seguridad al descargar un nuevo jar (etc.), por ejemplo, un hombre en el ataque medio. Siempre debe firmar su actualización descargable.

En JAX2015, Adam Bien contó sobre el uso de JGit para actualizar los binarios. Lamentablemente no pude encontrar ningún tutorial.

Source in German.

Adam Bien creó el programa de actualización see here

I en forma de horquilla que here con un poco de interfaz de JavaFX. También estoy trabajando en una firma automática.

Cuestiones relacionadas