¿Cómo implementar una aplicación Java de instancia única?

8 minutos de lectura

¿Como implementar una aplicacion Java de instancia unica
Fuangwith S.

En algún momento veo muchas aplicaciones como msn, Windows Media Player, etc. que son aplicaciones de instancia única (cuando el usuario ejecuta mientras la aplicación se está ejecutando, no se crea una nueva instancia de aplicación).

En C#, uso Mutex class para esto, pero no sé cómo hacerlo en Java.

  • Un enfoque muy simple con java NIO ver ejemplo completo stackoverflow.com/a/20015771/185022

    – AZ_

    16 de noviembre de 2013 a las 7:03


Utilizo el siguiente método en el método principal. Este es el método más simple, robusto y menos intrusivo que he visto, así que pensé en compartirlo.

private static boolean lockInstance(final String lockFile) {
    try {
        final File file = new File(lockFile);
        final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        final FileLock fileLock = randomAccessFile.getChannel().tryLock();
        if (fileLock != null) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        fileLock.release();
                        randomAccessFile.close();
                        file.delete();
                    } catch (Exception e) {
                        log.error("Unable to remove lock file: " + lockFile, e);
                    }
                }
            });
            return true;
        }
    } catch (Exception e) {
        log.error("Unable to create and/or lock file: " + lockFile, e);
    }
    return false;
}

  • ¿Cuál es el parámetro “lockFile” que debería ser para una aplicación de escritorio? el nombre del archivo jar de la aplicación? ¿Qué tal si no hay un archivo jar, solo algunos archivos de clase?

    – 5 años despuésDBA

    29 de julio de 2014 a las 14:09

  • ¿Es realmente necesario liberar manualmente el bloqueo del archivo y cerrar el archivo al apagarlo? ¿No sucede esto automáticamente cuando el proceso muere?

    – Natix

    7 oct 2014 a las 14:50

  • Pero, ¿qué sucede si se corta la energía y la computadora se apaga sin ejecutar el gancho de apagado? El archivo persistirá y la aplicación no se podrá iniciar.

    – Petr Hudeček

    13 de diciembre de 2014 a las 18:28

  • @PetrHudeček Está bien. No importa cómo finalice la aplicación, se liberará el bloqueo del archivo. Si no fue un apagado adecuado, esto incluso tiene la ventaja de permitir que la aplicación se dé cuenta de esto en la próxima ejecución. En cualquier caso: Lo que cuenta es el bloqueo, no la presencia del archivo en sí. Si el archivo aún está allí, la aplicación se iniciará de todos modos.

    – Presidente de Dreamspace

    21 de diciembre de 2015 a las 12:23

  • @Robert: Gracias por su solución, la he estado usando desde entonces. Y justo ahora, lo amplié para comunicarlo también a la instancia ya existente que otra instancia intentó iniciar, ¡usando la carpeta WatchService! stackoverflow.com/a/36772436/3500521

    – Presidente de Dreamspace

    21 de abril de 2016 a las 14:23

¿Como implementar una aplicacion Java de instancia unica
VonC

si creo esto artículopor :

hacer que la primera instancia intente abrir un socket de escucha en la interfaz localhost. Si puede abrir el socket, se supone que esta es la primera instancia de la aplicación que se inicia. De lo contrario, se supone que ya se está ejecutando una instancia de esta aplicación. La nueva instancia debe notificar a la instancia existente que se intentó un lanzamiento y luego salir. La instancia existente toma el control después de recibir la notificación y dispara un evento al oyente que maneja la acción.

Nota: Ahe menciona en el comentario que usando InetAddress.getLocalHost() puede ser complicado:

  • no funciona como se esperaba en un entorno DHCP porque la dirección devuelta depende de si la computadora tiene acceso a la red.
    La solución fue abrir la conexión con InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
    Probablemente relacionado con error 4435662.
  • también encontré error 4665037 que informa de los resultados esperados de getLocalHost: devuelve la dirección IP de la máquina, frente a los resultados reales: devuelve 127.0.0.1.

es sorprendente tener getLocalHost regreso 127.0.0.1 en Linux pero no en Windows.


O puede usar ManagementFactory objeto. Como se explica aquí:

los getMonitoredVMs(int processPid) El método recibe como parámetro el PID de la aplicación actual y captura el nombre de la aplicación que se llama desde la línea de comando, por ejemplo, la aplicación se inició desde c:\java\app\test.jar ruta, entonces la variable de valor es “c:\\java\\app\\test.jar“. De esta manera, capturaremos solo el nombre de la aplicación en la línea 17 del código a continuación.
Después de eso, buscamos en JVM otro proceso con el mismo nombre, si lo encontramos y el PID de la aplicación es diferente, significa que es la segunda instancia de la aplicación.

JNLP ofrece también una SingleInstanceListener

  • Tenga en cuenta que la primera solución tiene un error. Recientemente descubrimos que InetAddress.getLocalHost() no funciona como se esperaba en un entorno DHCP porque la dirección devuelta depende de si la computadora tiene acceso a la red. La solución fue abrir la conexión con InetAddress.getByAddress(new byte[] {127, 0, 0, 1});.

    – Ajá

    17 de septiembre de 2010 a las 8:31


  • @Ahe: excelente punto. Incluí su comentario, así como las referencias de informes de errores de Oracle-Sun en mi respuesta editada.

    – VoC

    17 de septiembre de 2010 a las 8:41

  • De acuerdo con JavaDoc InetAddress.getByName(null) devuelve la dirección de la interfaz de bucle invertido. Supongo que esto es mejor que especificar 127.0.0.1 manualmente porque, en teoría, esto también debería funcionar en entornos de solo IPv6.

    – kayahr

    9 de febrero de 2012 a las 8:55

  • Ver también Uso del servicio SingleInstanceService.

    – dios de la basura

    17 de enero de 2013 a las 16:56

  • @Puce Claro, no hay problema: he restaurado esos enlaces.

    – VoC

    23/09/2015 a las 17:46

1646748557 150 ¿Como implementar una aplicacion Java de instancia unica
andres thompson

Si la aplicación. tiene una GUI, inícielo con JWS y use el SingleInstanceService.

Actualizar

El complemento de Java (requerido tanto para los applets como para las aplicaciones JWS) quedó obsoleto por Oracle y se eliminó del JDK. Los fabricantes de navegadores ya lo habían eliminado de sus navegadores.

Así que esta respuesta está muerta. Solo lo dejo aquí para advertir a las personas que buscan documentación antigua.

  • También tenga en cuenta que parece que la instancia en ejecución puede recibir información sobre nuevas instancias y sus argumentos, lo que facilita la comunicación con dicho programa.

    – Thorbjorn Ravn Andersen

    26 de noviembre de 2012 a las 11:17

1646748558 332 ¿Como implementar una aplicacion Java de instancia unica
Parvez Ahmad

Sí, esta es una respuesta realmente decente para la aplicación de instancia única eclipse RCP eclipse a continuación es mi código

en aplicación.java

if(!isFileshipAlreadyRunning()){
        MessageDialog.openError(display.getActiveShell(), "Fileship already running", "Another instance of this application is already running.  Exiting.");
        return IApplication.EXIT_OK;
    } 


private static boolean isFileshipAlreadyRunning() {
    // socket concept is shown at http://www.rbgrn.net/content/43-java-single-application-instance
    // but this one is really great
    try {
        final File file = new File("FileshipReserved.txt");
        final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        final FileLock fileLock = randomAccessFile.getChannel().tryLock();
        if (fileLock != null) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        fileLock.release();
                        randomAccessFile.close();
                        file.delete();
                    } catch (Exception e) {
                        //log.error("Unable to remove lock file: " + lockFile, e);
                    }
                }
            });
            return true;
        }
    } catch (Exception e) {
       // log.error("Unable to create and/or lock file: " + lockFile, e);
    }
    return false;
}

Usamos el bloqueo de archivos para esto (obtener un bloqueo exclusivo en un archivo mágico en el directorio de datos de la aplicación del usuario), pero estamos interesados ​​​​principalmente en evitar que se ejecuten varias instancias.

Si está intentando que la segunda instancia pase argumentos de línea de comando, etc. a la primera instancia, entonces usar una conexión de socket en localhost matará dos pájaros de un tiro. Algoritmo general:

  • En el lanzamiento, intente abrir el oyente en el puerto XXXX en localhost
  • si falla, abra un escritor en ese puerto en localhost y envíe los argumentos de la línea de comando, luego apague
  • de lo contrario, escuche en el puerto XXXXX en localhost. Cuando reciba argumentos de línea de comando, procéselos como si la aplicación se hubiera iniciado con esa línea de comando.

¿Como implementar una aplicacion Java de instancia unica
Icono

He encontrado una solución, una explicación un poco caricaturesca, pero aún funciona en la mayoría de los casos. Utiliza el antiguo archivo de bloqueo simple para crear cosas, pero en una vista bastante diferente:

http://javalandscape.blogspot.com/2008/07/single-instance-from-your-application.html

Creo que será de ayuda para aquellos con una configuración de firewall estricta.

1646748560 685 ¿Como implementar una aplicacion Java de instancia unica
kolobok

Puede usar la biblioteca JUnique. Proporciona soporte para ejecutar una aplicación Java de instancia única y es de código abierto.

http://www.sauronsoftware.it/projects/junique/

La biblioteca JUnique se puede utilizar para evitar que un usuario ejecute al mismo tiempo más instancias de la misma aplicación Java.

JUnique implementa bloqueos y canales de comunicación compartidos entre todas las instancias de JVM lanzadas por el mismo usuario.

public static void main(String[] args) {
    String appId = "myapplicationid";
    boolean alreadyRunning;
    try {
        JUnique.acquireLock(appId, new MessageHandler() {
            public String handle(String message) {
                // A brand new argument received! Handle it!
                return null;
            }
        });
        alreadyRunning = false;
    } catch (AlreadyLockedException e) {
        alreadyRunning = true;
    }
    if (!alreadyRunning) {
        // Start sequence here
    } else {
        for (int i = 0; i < args.length; i++) {
            JUnique.sendMessage(appId, args[0]));
        }
    }
}

Bajo el capó, crea bloqueos de archivos en la carpeta %USER_DATA%/.junique y crea un socket de servidor en un puerto aleatorio para cada ID de aplicación único que permite enviar/recibir mensajes entre aplicaciones Java.

  • ¿Puedo usar esto para evitar múltiples instancias de la aplicación Java en una red? es decir, solo se permite una instancia de mi aplicación en toda mi red

    – Wuaner

    25 de abril de 2017 a las 2:29

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad