Domanda

ho bisogno di impedire agli utenti di iniziare la mia applicazione Java (WebStart swing app) più volte. Quindi, se l'applicazione è già in esecuzione non dovrebbe essere possibile avviare di nuovo o di mostrare un avviso / essere chiuso di nuovo.

C'è un modo conveniente per raggiungere questo obiettivo? Ho pensato di blocco di una porta o di scrittura sth in un file. Ma si spera si può accedere ad alcune proprietà del sistema o la JVM?

btw. piattaforma di destinazione è Windows XP con Java 1.5

È stato utile?

Soluzione

Credo che la tua proposta di aprire una porta per ascoltare quando si avvia l'applicazione è l'idea migliore.

E 'molto facile da fare e non c'è bisogno di preoccuparsi di pulirlo quando si chiude l'applicazione. Ad esempio, se si scrive in un file ma qualcuno uccide poi i processi utilizzando Task Manager il file non andranno eliminati.

Inoltre, se non ricordo male non esiste un modo semplice di ottenere il PID di un processo Java dall'interno della JVM in modo da non cercare di formulare una soluzione con PID.

Qualcosa del genere dovrebbe fare il trucco:

private static final int PORT = 9999;
private static ServerSocket socket;    

private static void checkIfRunning() {
  try {
    //Bind to localhost adapter with a zero connection queue 
    socket = new ServerSocket(PORT,0,InetAddress.getByAddress(new byte[] {127,0,0,1}));
  }
  catch (BindException e) {
    System.err.println("Already running.");
    System.exit(1);
  }
  catch (IOException e) {
    System.err.println("Unexpected error.");
    e.printStackTrace();
    System.exit(2);
  }
}

Questo codice di esempio si lega esplicitamente a 127.0.0.1 che dovrebbe evitare eventuali avvisi del firewall, come tutto il traffico su questo indirizzo deve essere dal sistema locale.

Al momento del ritiro una porta cercare di evitare quella menzionata nella lista di porte Well Known . Si dovrebbe idealmente rendere la porta utilizzata configurabile in un file o tramite un interruttore riga di comando in caso di conflitti.

Altri suggerimenti

Dato che la questione afferma che WebStart è in uso, la soluzione più ovvia è quella di utilizzare javax.jnlp.SingleInstanceService .

Il servizio è disponibile in 1.5. Si noti che 1.5 è attualmente la maggior parte del modo attraverso il suo termine del periodo di servizio Vita. Ottenere con Java SE 6!

Credo che l'idea migliore sarebbe quella di utilizzare il blocco di file (piuttosto una vecchia idea :)). Dal momento che Java 1.4 un nuovo mi è stato introdotto biblioteca / O, che permette il blocco dei file.

Una volta che l'applicazione si avvia il tentativo di acquisizione di blocco su un file (o crearlo se non esiste), quando l'applicazione esce il blocco è relased. Se l'applicazione non è in grado di acquisire un blocco, si chiude.

L'esempio come fare il blocco dei file è per esempio in sviluppatori Java Almanac .

Se si desidera utilizzare il blocco dei file in un'applicazione Java Web Start o un applet è necessario cantare l'applicazione o l'applet.

Facciamo lo stesso in C ++ con la creazione di un oggetto mutex kernal e cerca di esso all'avvio. I vantaggi sono gli stessi mediante una presa, cioè quando il processo muore / crash / uscite / è ucciso, l'oggetto mutex viene pulito dal kernel.

Io non sono un programmatore Java, quindi non sono sicuro se si può fare lo stesso tipo di cosa in Java?

È possibile utilizzare libreria JUnique. Esso fornisce supporto per l'esecuzione dell'applicazione Java istanza singola ed è open-source.

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

Si veda anche la mia risposta completa al Come implementare una singola istanza di un'applicazione Java?

ho creare la classe piattaforma di AppLock croce.

http: //rumatoest.blogspot .com / 2015/01 / howto-run-solo-single-java-application.html

Si sta usando la tecnica di blocco del file.

Aggiornamento. A 2016/10/14 Ho creato il pacchetto compatibile con Maven / Gradle https://github.com/jneat/ jneat e spiegato qui http: / /rumatoest.blogspot.com/2015/06/synchronize-code-over-multiple-jvm.html

È possibile utilizzare il Registro di sistema, anche se questo sconfigge malavoglia lo scopo di utilizzare un linguaggio di alto livello come Java. Almeno la piattaforma di destinazione è Windows = D

Prova JUnique:

String appId = "com.example.win.run.main";
boolean alreadyRunning;
try {
    JUnique.acquireLock(appId);
    alreadyRunning = false;
} catch (AlreadyLockedException e) {
    alreadyRunning = true;
}
if (alreadyRunning) {
    Sysout("An Instance of this app is already running");
    System.exit(1);
}

Ho visto tanti di queste domande e stavo cercando di risolvere lo stesso problema in una piattaforma maniera indipendente che non prende la possibilità di entrare in collisione con i firewall o entrare in roba presa.

Quindi, ecco quello che ho fatto:

import java.io.File;
import java.io.IOException;

/**
 * This static class is in charge of file-locking the program
 * so no more than one instance can be run at the same time.
 * @author nirei
 */
public class SingleInstanceLock {

    private static final String LOCK_FILEPATH = System.getProperty("java.io.tmpdir") + File.separator + "lector.lock";
    private static final File lock = new File(LOCK_FILEPATH);
    private static boolean locked = false;

    private SingleInstanceLock() {}

    /**
     * Creates the lock file if it's not present and requests its deletion on
     * program termination or informs that the program is already running if
     * that's the case.
     * @return true - if the operation was succesful or if the program already has the lock.<br>
     * false - if the program is already running
     * @throws IOException if the lock file cannot be created.
     */
    public static boolean lock() throws IOException {
        if(locked) return true;

        if(lock.exists()) return false;

        lock.createNewFile();
        lock.deleteOnExit();
        locked = true;
        return true;
    }
}

Utilizzo System.getProperty ( "java.io.tmpdir") per il percorso di file di lock fa in modo che vi sarà sempre creare il blocco nello stesso posto.

Poi, dal vostro programma basta chiamare qualcosa come:

blah blah main(blah blah blah) {
    try() {
        if(!SingleInstanceLock.lock()) {
            System.out.println("The program is already running");
            System.exit(0);
        }
    } catch (IOException e) {
        System.err.println("Couldn't create lock file or w/e");
        System.exit(1);
    }
}

E questo lo fa per me. Ora, se si uccide il programma non sarà eliminare il file di blocco, ma si riesce a risolvere questo scrivendo PID del programma nel file di lock e rendendo il metodo di controllo di blocco () se tale processo è già in esecuzione. Questo viene lasciato come assingment per chiunque sia interessato. :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top