[java] 런타임에 스스로 업데이트 할 수있는 Java 애플리케이션을 어떻게 작성할 수 있습니까?

주어진 URL에서 새 버전 (.jar 파일)을 다운로드 한 다음 런타임에 업데이트 할 수있는 Java 응용 프로그램 (서버 응용 프로그램)을 구현하고 싶습니다.

이를 수행하는 가장 좋은 방법은 무엇이며 가능합니까?

응용 프로그램이 새 .jar 파일을 다운로드하여 시작할 수 있다고 생각합니다. 그러나 어떻게 핸드 오버를해야합니까? 예를 들어 새 응용 프로그램이 언제 시작되고 종료되는지 알 수 있습니다. 아니면 더 좋은 방법이 있습니까?



답변

솔루션의 기본 구조는 다음과 같습니다.

  • 앱의 최신 버전을 반복적으로로드하고 (필요한 경우) 실행하는 메인 루프가 있습니다.

  • 응용 프로그램은 그 일을하지만 주기적으로 다운로드 URL을 확인합니다. 새 버전을 감지하면 런처로 돌아갑니다.

이를 구현할 수있는 방법에는 여러 가지가 있습니다. 예를 들면 :

  • 런처는 대체되는 JAR 파일에서 애플리케이션을 실행하기 위해 새 JVM을 시작하는 랩퍼 스크립트 또는 바이너리 애플리케이션 일 수 있습니다.

  • 런처는 새 JAR에 대한 클래스 로더를 작성하고 진입 점 클래스를로드하고 여기에 일부 메소드를 호출하는 Java 애플리케이션 일 수 있습니다. 이런 식으로하면 클래스 로더 저장소 누수를 감시해야하지만 어렵지 않습니다. (재실행 후 JAR에서로드 된 클래스가있는 객체에 도달 할 수 없는지 확인하기 만하면됩니다.)

외부 래퍼 접근 방식의 장점은 다음과 같습니다.

  • JAR 하나만 필요합니다.
  • 전체 Java 앱을 대체 할 수 있습니다.
  • 앱 등에서 생성 된 보조 스레드는 특별한 종료 로직없이 사라집니다.
  • 응용 프로그램 충돌 등으로부터 복구를 처리 할 수도 있습니다.

두 번째 접근 방식에는 두 개의 JAR이 필요하지만 다음과 같은 이점이 있습니다.

  • 솔루션은 순수 Java이며 이식 가능합니다.
  • 전환이 더 빨라지고
  • 다시 시작하는 동안 상태를 더 쉽게 유지할 수 있습니다 (모듈로 누출 문제).

“최상의”방법은 특정 요구 사항에 따라 다릅니다.

또한 다음 사항에 유의해야합니다.

  • 자동 업데이트에는 보안 위험이 있습니다. 일반적으로 업데이트를 제공하는 서버가 손상되었거나 업데이트를 제공하는 메커니즘이 공격에 취약한 경우 자동 업데이트로 인해 클라이언트가 손상 될 수 있습니다.

  • 고객에게 피해를주는 업데이트를 고객에게 푸시하면 법적 위험이있을 수 있으며 비즈니스 평판에 위험이 발생할 수 있습니다.


바퀴를 재발 명하지 않는 방법을 찾을 수 있다면 좋을 것입니다. 제안 사항은 다른 답변을 참조하십시오.


답변

저는 현재 JAVA Linux Daemon을 개발 중이며 자동 업데이트 메커니즘을 구현해야했습니다. 내 응용 프로그램을 하나의 jar 파일로 제한하고 간단한 해결책을 찾았습니다.

업데이트 자체에 업데이트 프로그램 응용 프로그램을 압축합니다.

응용 프로그램 : 응용 프로그램이 최신 버전을 감지하면 다음을 수행합니다.

  1. 업데이트 다운로드 (Zipfile)
  2. 응용 프로그램 및 ApplicationUpdater 추출 (모두 zip 파일에 있음)
  3. 업데이터 실행

ApplicationUpdater : 업데이트 프로그램이 실행되면 다음을 수행합니다.

  1. 응용 프로그램을 중지하십시오 (제 경우에는 init.d를 통한 데몬)
  2. 다운로드 한 jar 파일을 복사하여 현재 애플리케이션을 덮어 씁니다.
  3. 응용 프로그램 시작
  4. 대청소.

누군가에게 도움이되기를 바랍니다.


답변

이것은 알려진 문제이며 바퀴를 재발 명하지 않는 것이 좋습니다. 자신의 해킹을 작성하지 말고 다른 사람들이 이미 한 것을 사용하십시오.

고려해야 할 두 가지 상황 :

  1. 앱은 자체 업데이트가 가능하고 업데이트 중에도 계속 실행되어야합니다 (서버 앱, 임베디드 앱). OSGi로 이동 : 번들 또는 Equinox p2 .

  2. 앱은 데스크톱 앱이며 설치 프로그램이 있습니다. 업데이트 옵션이있는 설치 프로그램이 많이 있습니다. 설치자 목록을 확인하십시오 .


답변

최근 Java 9의 모듈 시스템과 완벽하게 호환되는 update4j 를 만들었습니다 .

다시 시작하지 않고도 새 버전을 원활하게 시작합니다.


답변

jEdit의 유사한 메커니즘에서 영감을 받아 런타임에 플러그인을로드하고 즉시 사용할 수있는 Java 애플리케이션을 작성했습니다. jEdit는 오픈 소스이므로 작동 방식을 볼 수있는 옵션이 있습니다.

이 솔루션은 사용자 정의 ClassLoader를 사용하여 jar에서 파일을로드합니다. 일단로드되면 새 jar에서 해당 main메서드 로 작동 할 메서드를 호출 할 수 있습니다 . 그런 다음 까다로운 부분은 가비지 수집이 가능하도록 이전 코드에 대한 모든 참조를 제거하는 것입니다. 나는 그 부분에 대한 전문가가 아니고 그것을 작동하도록 만들었지 만 쉽지 않았습니다.


답변

  1. 첫 번째 방법 : 바람둥이를 사용하고 시설을 배포합니다.
  2. 두 번째 방법 : 응용 프로그램을 두 부분 (기능 및 업데이트)으로 분할하고 업데이트 부분이 기능 부분을 대체하도록합니다.
  3. 세 번째 방법 : 서버 응용 프로그램에서 새 버전을 다운로드 한 다음 이전 버전이 바인딩 된 포트를 릴리스 한 다음 이전 버전이 새 버전을 실행 (프로세스 시작) 한 다음 이전 버전이 응용 프로그램 포트에 대한 요청을 새 버전으로 전송하여 이전 버전, 이전 버전을 삭제합니다. 종료되고 새 버전은 이전 버전을 삭제합니다. 이렇게 :
    대체 텍스트


답변

이것이 반드시 최고 는 아닙니다. 방법은 아니지만 귀하에게 적합 할 수 있습니다.

부트 스트랩 애플리케이션을 작성할 수 있습니다 (WoW를 플레이 한 경우 월드 오브 워크래프트 런처라고도 함). 해당 부트 스트랩은 업데이트 확인을 담당합니다.

  • 사용 가능한 업데이트가 있으면 사용자에게 제공하고 다운로드, 설치 등을 처리합니다.
  • 응용 프로그램이 최신 상태이면 사용자가 응용 프로그램을 시작할 수 있습니다.
  • 선택적으로 최신 상태가 아니더라도 사용자가 애플리케이션을 실행하도록 허용 할 수 있습니다.

이렇게하면 애플리케이션을 강제 종료하는 것에 대해 걱정할 필요가 없습니다.

애플리케이션이 웹 기반이고 최신 클라이언트가 있어야하는 경우 애플리케이션이 실행되는 동안 버전 확인을 수행 할 수도 있습니다. 서버와의 정상적인 통신 (일부 또는 모든 호출) 또는 둘 다를 수행하면서 간격을두고 수행 할 수 있습니다.

최근에 작업 한 제품의 경우 시작시 (부트 스트 래퍼 앱없이 기본 창이 표시되기 전) 및 서버 호출 중에 버전 확인을 수행했습니다. 클라이언트가 오래되었을 때 우리는 사용자가 수동으로 종료하도록 의존했지만 서버에 대한 어떠한 조치도 금지했습니다.

메인 창을 열기 전에 Java가 UI 코드를 호출 할 수 있는지 알 수 없습니다. 우리는 C # / WPF를 사용하고있었습니다.