한 번에 Java 프로그램의 하나의 인스턴스 만 실행할 수있는 방법은 무엇입니까?

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

  •  06-09-2019
  •  | 
  •  

문제

사용자가 Java 응용 프로그램 (WebStart Swing App)을 여러 번 시작하는 것을 방지해야합니다. 따라서 응용 프로그램이 이미 실행중인 경우 다시 시작하거나 경고를 표시하거나 다시 닫을 수 없습니다.

이것을 달성 할 수있는 편리한 방법이 있습니까? 포트를 차단하거나 파일에 STH를 쓰는 것에 대해 생각했습니다. 그러나 일부 시스템 속성이나 JVM에 액세스 할 수 있기를 바랍니다.

BTW. 대상 플랫폼은 Java 1.5가있는 Windows XP입니다

도움이 되었습니까?

해결책

응용 프로그램을 시작할 때들을 수있는 포트를 열 겠다는 제안이 가장 좋은 아이디어라고 생각합니다.

할 수있는 것은 매우 쉽고 응용 프로그램을 닫을 때 청소에 대해 걱정할 필요가 없습니다. 예를 들어, 파일에 쓰지 만 누군가가 작업 관리자를 사용하여 프로세스를 죽인 경우 파일은 삭제되지 않습니다.

또한 올바르게 기억한다면 JVM 내부에서 Java 프로세스의 PID를 쉽게 얻을 수있는 방법이 없으므로 PID를 사용하여 솔루션을 공식화하지 마십시오.

이와 같은 것은 트릭을 수행해야합니다.

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

이 샘플 코드는 명시 적으로 바인딩됩니다 127.0.0.1 이 주소의 트래픽은 로컬 시스템에서 이루어져야하므로 방화벽 경고를 피해야합니다.

포트를 선택할 때 항구에 언급 된 항구를 피하려고 잘 알려진 포트 목록. 충돌의 경우 파일 또는 명령 줄 스위치를 통해 구성 가능한 포트를 이상적으로 만들어야합니다.

다른 팁

질문에 WebStart가 사용되고 있다고 명시된 것처럼 명백한 해결책은 사용하는 것입니다. javax.jnlp.SingleInstanceService.

이 서비스는 1.5로 제공됩니다. 1.5는 현재 서비스 종료 수명 기간 동안 대부분의 방식입니다. Java SE 6로 가십시오!

더 나은 아이디어는 파일 잠금을 사용하는 것입니다 (꽤 오래된 아이디어 :)). Java 1.4 이후 새로운 I/O 라이브러리가 도입되어 파일 잠금을 허용합니다.

애플리케이션이 시작되면 파일에서 잠금을 취득하려고 시도하거나 (존재하지 않으면) 응용 프로그램이 잠금을 종료하면 잠금이 상사됩니다. 애플리케이션이 잠금을 얻을 수없는 경우 종료됩니다.

예를 들어 파일 잠금 방법은 예를 들어 Java 개발자 Almanac.

Java 웹 시작 응용 프로그램 또는 애플릿에서 파일 잠금을 사용하려면 응용 프로그램이나 애플릿을 노래해야합니다.

우리는 Kernal Mutex 객체를 만들고 시작시 그것을 찾아 C ++에서 동일하게 수행합니다. 장점은 소켓을 사용하는 것과 동일합니다. 즉, 프로세스가 사망/충돌/종료/사망 할 때 MUTEX 물체는 커널에 의해 정리됩니다.

나는 Java 프로그래머가 아니므로 Java에서 같은 종류의 일을 할 수 있는지 확실하지 않습니까?

Junique Library를 사용할 수 있습니다. 단일 인스턴스 Java 응용 프로그램 실행을 지원하며 오픈 소스입니다.

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

내 전체 답변을 참조하십시오 단일 인스턴스 Java 응용 프로그램을 구현하는 방법은 무엇입니까?

크로스 플랫폼 Applock 클래스를 만듭니다.

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

파일 잠금 기술을 사용하고 있습니다.

업데이트. 2016-10-14 년에 나는 Maven/Gradle과 호환되는 패키지를 만들었습니다. https://github.com/jneat/jneat 여기에 설명했습니다 http://rumatoest.blogspot.com/2015/06/synchronize-code-over-multiple-jvm.html

이 반은 Java와 같은 고급 언어를 사용하는 목적을 상심하게 패배하지만 레지스트리를 사용할 수 있습니다. 최소한 대상 플랫폼은 Windows = d입니다

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

나는이 질문들을 너무 많이 보았고 방화벽과 충돌하거나 소켓에 들어갈 수있는 기회를 갖지 않는 플랫폼 독립적 인 방식으로 동일한 문제를 해결하려고했습니다.

그래서 여기 내가 한 일이 있습니다.

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

Lockfile 경로의 System.getProperty ( "java.io.tmpdir")를 사용하면 항상 같은 장소에 잠금 장치를 만들 수 있습니다.

그런 다음 프로그램에서 다음과 같은 것을 호출합니다.

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

그리고 그것은 나를 위해 그것을합니다. 이제 프로그램을 죽이면 잠금 파일을 삭제하지는 않지만 프로그램의 PID를 LockFile에 작성하고 잠금 () 메소드를 해당 프로세스가 이미 실행 중인지 확인하여이를 해결할 수 있습니다. 이것은 관심있는 사람을위한 분석으로 남아 있습니다. :)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top