Wie zu erlauben, zu einem Zeitpunkt nur eine Instanz eines Java-Programms ausgeführt wird?

StackOverflow https://stackoverflow.com/questions/920386

  •  06-09-2019
  •  | 
  •  

Frage

Ich muss verhindern, dass Benutzer von meiner Java-Anwendung starten (WebStart Swing-app) mehrere Male. Also, wenn die Anwendung bereits ausgeführt wird es nicht möglich sein, sollte es wieder zu starten oder eine Warnung / wieder geschlossen werden.

Gibt es eine bequeme Möglichkeit, dies zu erreichen? Ich dachte über einen Port oder Schreib etw in eine Datei zu blockieren. Aber hoffentlich können Sie einige Systemeigenschaften zugreifen oder die JVM?

btw. Zielplattform Windows XP mit Java 1.5

War es hilfreich?

Lösung

Ich denke, Ihr Vorschlag, einen Port zu öffnen, zu hören, wenn Sie die Anwendung starten, ist die beste Idee.

Es ist sehr einfach zu tun, und Sie müssen nicht über die Reinigung es bis kümmern, wenn Sie die Anwendung schließen. wenn Sie eine Datei zum Beispiel schreiben, aber jemand tötet dann die Prozesse mit dem Task-Manager die Datei nicht gelöscht.

Auch wenn ich mich richtig erinnere sich keine einfache Möglichkeit ist PIDs des Erhaltens der PID eines Java-Prozesses aus dem Innern des JVM also nicht versuchen und zu formulieren, um eine Lösung verwendet wird.

So etwas sollte es tun:

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);
  }
}

Dieser Beispielcode bindet explizit 127.0.0.1 die Firewall-Warnungen vermeiden sollte, da jeder Verkehr auf dieser Adresse aus dem lokalen System sein muss.

Wenn Sie einen Port Kommissionierung versuchen, eine in der Liste Bekannte Ports erwähnt zu vermeiden . Sie sollten idealerweise die Port machen in einer Datei konfigurierbar verwendet oder über einen Befehlszeilenschalter im Falle von Konflikten.

Andere Tipps

Da die Frage stellt fest, dass WebStart verwendet wird, die offensichtliche Lösung ist javax.jnlp.SingleInstanceService .

Dieser Service ist in 1.5 zur Verfügung. Beachten Sie, dass 1.5 ist derzeit die meisten der Weg durch das Ende ihrer Nutzungsdauer Lebensdauer. Setzen Sie sich mit Java SE 6!

Ich denke, dass die bessere Idee wäre Dateisperre zu verwenden (ganz eine alte Idee :)). Da Java 1.4 ein neues I / O-Bibliothek eingeführt wurde, ermöglicht es, die Dateisicherung.

Sobald die Anwendung gestartet wird es versucht, Sperre für eine Datei zu erwerben (oder es schaffen, wenn nicht vorhanden), wenn die Anwendung beendet das Schloss relased wird. Wenn die Anwendung nicht eine Sperre erwerben kann, es beendet wird.

Das Beispiel, wie das Sperren von Dateien zu tun ist, zum Beispiel in Java Entwicklern Almanach .

Wenn Sie in der Anwendung Java Web Start-Dateisperren verwenden oder ein Applet Sie die Anwendung singen müssen, oder das Applet.

Wir tun das gleiche in C ++ durch ein kernal Mutex-Objekt erstellen und suchen sie beim Start. Die Vorteile sind die gleichen wie eine Buchse verwendet wird, dh, wenn der Prozess stirbt / Abstürze / Ausgänge / ist getötet wird das Mutex-Objekt vom Kernel gereinigt.

Ich bin kein Java-Programmierer, so dass ich bin mir nicht sicher, ob Sie die gleiche Art von Dingen in Java tun können?

Sie können Junique Bibliothek verwenden. Es bietet Unterstützung für Single-Instance-Java-Anwendung ausgeführt und ist Open-Source.

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

Sehen Sie meine vollständige Antwort auf auch So implementieren eine einzelne Instanz Java-Anwendung?

Ich habe die Cross-Plattform-AppLock Klasse erstellen.

http: //rumatoest.blogspot .com / 2015/01 / Howto-run-only-Single-java-application.html

Es Dateisperre Technik verwendet wird.

Update. Bei 2016.10.14 Ich habe Paket erstellt kompatibel mit Maven / gradle https://github.com/jneat/ jneat und erklärt hier http: / /rumatoest.blogspot.com/2015/06/synchronize-code-over-multiple-jvm.html

Sie könnten die Registrierung verwenden, obwohl dies mit halbem Herzen, den Zweck der Verwendung einer Hochsprache wie Java besiegt. Mindestens Ihre Zielplattform ist Windows = D

Versuchen 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);
}

Ich habe so viele diese Fragen gesehen, und ich war auf der Suche das gleiche Problem in einer plattformunabhängigen Art und Weise zu lösen, die nicht die Chance, mit Firewalls kollidiert nehmen oder in der Buchse Sachen bekommen.

So, hier ist was ich getan habe:

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;
    }
}

Mit System.getProperty ( „java.io.tmpdir“) für den lockfile Weg stellt sicher, dass Sie immer Ihre Schloss an der gleichen Stelle erstellen.

Dann aus Ihrem Programm rufen Sie einfach so etwas wie:

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);
    }
}

Und das tut es für mich. Nun, wenn Sie das Programm töten wird es nicht die Sperrdatei löschen, aber Sie können dieses Problem lösen, indem das Programm die PID in die Lock-Datei zu schreiben und machen das Schloss () Methode zu überprüfen, ob dieser Prozess bereits ausgeführt wird. Dies bleibt als assingment für alle Interessierten. :)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top