Wie stelle ich sicher, dass nur eine einzige Instanz einer Java-Anwendung ausgeführt wird?

8

Ich möchte, dass meine Anwendung prüft, ob bereits eine andere Version von sich selbst läuft.

Beispiel: demo.jar wurde gestartet, der Benutzer klickt, um es erneut auszuführen, aber die zweite Instanz erkennt "oh, warte, da ist bereits demo.jar running". und wird mit einer Nachricht beendet.

    
Epicblood 09.05.2012, 01:46
quelle

12 Antworten

5

Was Sie suchen, können Sie wahrscheinlich am besten mit einer Sperrdatei erreichen. Mit Sperrdatei meine ich einfach eine Datei, die einen vordefinierten Ort hat und deren Existenz Ihr Mutex ist.

Testen Sie, ob diese Datei beim Programmstart vorhanden ist. Ist dies der Fall, beenden Sie sie sofort. Erstellen Sie eine Datei an einem bekannten Speicherort. Wenn das Programm normal beendet wird, löschen Sie die Sperrdatei.

Wahrscheinlich ist es am besten, wenn Sie die Datei auch mit einer PID (Prozess-ID) auffüllen können, so dass Sie anormale Exits erkennen können, die die Datei nicht gelöscht haben, aber dies wird für das Betriebssystem spezifisch.

    
Andrew White 09.05.2012, 01:52
quelle
7

Erzwingt eine Instanz eines Programms, das mit einer ServerSocket-Sperre ausgeführt wird

Java-Code. Legen Sie dies in eine Datei namens Main.java:

%Vor%

Kompilieren und ausführen

%Vor%

Testen Sie es im Normalfall:

Führen Sie das Programm aus. Sie haben 100 Sekunden Zeit, um das Programm erneut in einem anderen Terminal auszuführen, es wird durchgehen und sagen, dass es bereits läuft. Dann warten Sie 100 Sekunden, es sollte Ihnen erlauben, es im 2. Terminal zu laufen.

Testen Sie es nach dem Beenden des Programms mit einem Kill -9

  1. Starten Sie das Programm in Terminal 1.
  2. kill -9 diesen Prozess von einem anderen Terminal innerhalb von 100 Sekunden.
  3. Führe das Programm erneut aus, es kann ausgeführt werden.

Fazit:

Die Socket-Belegung wird vom Betriebssystem bereinigt, wenn Ihr Programm nicht mehr funktioniert. So können Sie sicher sein, dass das Programm nicht zweimal ausgeführt wird.

Nachteile

Wenn irgendeine hinterhältige Person oder irgendein ungezogener Prozess alle Ports oder nur Ihren Port binden würde, wird Ihr Programm nicht ausgeführt, weil es denkt, dass es bereits läuft.

    
Eric Leschinski 14.08.2014 19:45
quelle
5
  

Einfache, aber leistungsstarke getestete Lösung.

%Vor%

Setzen Sie diese Methoden in eine Util-Klasse und überprüfen Sie vor dem Start der Hauptklasse, ob sie bereits existiert, und zeigen Sie dann dem Benutzer ein Dialogfeld, um eine Anwendung zu starten. Es funktioniert auch, wenn Sie den Java-Prozess abnormal herunterfahren oder was auch immer Sie tun. Es ist robust und effizient, keine DataGram-Listener oder was auch immer einzurichten ...

    
AZ_ 16.11.2013 07:01
quelle
2

Wenn Sie einen Mutex verwenden, müsste Mutex logisch von jeder JVM aus zugänglich sein, auf der eine Kopie von "the program" läuft. In der C-Programmierung könnte dies über Shared Memory erreicht werden, aber Java hat standardmäßig keine solche Funktion.

Mit diesem Verständnis gibt es viele Möglichkeiten, das zu implementieren, was Sie wollen. Sie können einen Server-Socket an einem bestimmten Port öffnen (das Betriebssystem stellt sicher, dass nur ein Prozess der Empfänger des Server-Sockets ist und nachfolgende Open-Downs fehlschlagen).

Sie könnten eine "Sperrdatei" verwenden, aber es ist ein wenig kompliziert, da die Datei, die Sie verwenden müssten, ein Verzeichnis wäre (und es hängt stark davon ab, ob die Verzeichniserstellung für Ihr Dateisystem atomar ist) meisten Verzeichnis-Kreationen sind). Wenn ein Systemadministrator entscheidet, Sie über NFS laufen zu lassen, wird es noch schwieriger (wenn nicht unmöglich).

Sie können auch eine Reihe von raffinierten Tricks mit JVMs und Debugging / JMI machen, vorausgesetzt, Sie können sich irgendwie versichern, dass alle relevanten JVMs mit den gleichen Konfigurationen gestartet werden (rechtzeitig, eine unmögliche Aufgabe).

Andere Leute haben die Exec-Einrichtung verwendet, um das Äquivalent einer Prozessliste zu führen, aber es ist ein bisschen schwierig wegen der Möglichkeit von Race Condition (zwei Prozesse gleichzeitig prüfen und einander nicht sehen).

Am Ende ist die Server-Socket-Route wahrscheinlich die stabilste, da sie garantiert nur vom TCP / IP-Stack an einen Prozess gebunden wird (und vom Betriebssystem vermittelt wird). Das heißt, Sie müssen den Socket von eingehenden Nachrichten leeren, und es eröffnet die Möglichkeit anderer Sicherheitsprobleme.

    
Edwin Buck 09.05.2012 01:59
quelle
2

Wenn Ihre Anwendung unter Windows ausgeführt wird, können Sie CreateMutex über JNI aufrufen.

%Vor%

Dies gibt true zurück, wenn niemand sonst diesen Mutex verwendet, andernfalls false. Sie können "myApplication" als Mutex-Name oder "Global \ MyApplication" angeben, wenn Sie möchten, dass Ihr Mutex von allen Windows-Sitzungen gemeinsam genutzt wird.

Bearbeiten: Es ist nicht so kompliziert wie es aussieht :) und ich finde es sauber.

    
Jerome 09.05.2012 02:00
quelle
2

Die Strategie dieses Codes besteht darin, die PID von der letzten Ausführung in der Registrierung aus beizubehalten. Wenn diese PID auf dem System gefunden wird, starten Sie nicht. Wenn Sie fertig sind, zurücksetzen.

Die Einstellungen werden in der Windows-Registrierung in HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefs

gespeichert %Vor%

Wenn das Programm hängt und die PID in der Aufgabenliste bleibt, wird dies blockiert. Sie könnten einen zusätzlichen Registrierungsschlüssel hinzufügen, der die letzte erfolgreiche Laufzeit speichert. Wenn die Laufzeit zu groß wird, wird die gespeicherte PID gelöscht und das Programm erneut ausgeführt.

    
Eric Leschinski 02.08.2013 03:36
quelle
0

Im Gegensatz zu einigen anderen Antworten ist die zuverlässigste Methode, ein ServerSocket auf einem festen Port zu erstellen, der nur Ihnen bekannt ist, weit oben in den Malkarten. Es wird automatisch freigegeben, wenn Ihre Anwendung beendet wird, anders als jede Sperrdatei, und ihre vorherige Existenz über ein BindException ist ein ziemlich unfehlbares Zeichen dafür, dass bereits eine andere Instanz läuft.

    
EJP 16.11.2013 07:20
quelle
0

Dies ist auch eine gute Lösung, wenn Ihre Anwendung im Task-Manager mit einem eindeutigen Namen geplant werden kann

%Vor%     
user3906011 11.09.2014 07:29
quelle
0

Nachfolgende Lösungsarbeit in zwei tödlichen Szenerien. 1 & gt; Sogar Ihre gestartete Exe ist als javaw.exe im Task-Manager geplant. 2 & gt; Sie können Ihre Anwendung an zwei Orten installieren, und vom Starten beider Standorte aus funktioniert es auch.

%Vor%

oder

Dies funktioniert, wenn Ihre Anwendung im Task-Manager

aufgeführt ist %Vor%     
user3906011 11.09.2014 06:55
quelle
0

Überprüfen Sie die PID- und Dateisperrtechnik

Wir können die Prozess-ID des Prozesses, der die Sperrdatei erstellt hat, in die Datei schreiben. Wenn wir auf eine vorhandene Sperrdatei stoßen, beenden wir nicht einfach, sondern prüfen, ob der Prozess mit dieser ID noch aktiv ist. Wenn nicht, erstellen Sie eine neue Anwendungsinstanz. Ich denke MongoDB verwendet diese Technik.

%Vor%     
Kunal 15.09.2014 08:31
quelle
0

Hier ist eine Methode, die eine automatisch benannte Sperrdatei im Home-Verzeichnis des Benutzers verwendet. Der Name basiert auf dem Ort, von dem aus das jar ausgeführt wird.

'' '

%Vor%

'' '

    
Michael Joyner 01.08.2016 16:21
quelle
-1

FileLock funktioniert nicht unter Linux. Bitte benutze FileLock nicht. Ich denke, den Namen des Prozesses zu bekommen (indem ich einen eindeutigen Namen erstelle, wenn möglich) wäre eine Möglichkeit, dieses Problem anzugehen. Ich denke, dass Prozess-ID automatisch zugewiesen ist.

Beziehen Sie sich auf den Prozess:

  

Ссылка

    
Mukus 11.07.2012 03:47
quelle

Tags und Links