Çalışma zamanında kendini güncelleyebilen bir Java uygulamasını nasıl yazabilirim?


91

Belirli bir url'den yeni bir sürümü (.jar dosyası) indirebilen ve ardından çalışma zamanında kendini güncelleyebilen bir java uygulaması (sunucu uygulaması) uygulamak istiyorum.

Bunu yapmanın en iyi yolu nedir ve bu mümkün mü?

Sanırım uygulama yeni bir .jar dosyası indirip başlatabilir. Ama geçişi nasıl yapmalıyım, örneğin yeni uygulamanın ne zaman başladığını ve sonra çıktığını bilmek. Yoksa bunu yapmanın daha iyi bir yolu var mı?


4
Java Web Start'a baktınız mı? Yine de çalışma zamanında kendini güncellemiyor, inanıyorum ki (yeniden başlatma gerekiyor), çünkü muhtemelen OSGi'ye bakmanız gerekiyor.
Thilo

@Thilo: Belirli bir url'den bir dosya indirmenin ve ardından çalışan jar dosyasından bir linux komutuyla başlatmanın kolay olacağını düşünüyorum.
Jonas

1
Java WebStart API'nin tasarımı, çalışırken güncelleme yapılmasını imkansız kılar. Ne yazık ki.
Thorbjørn Ravn Andersen


@meain boss you rock, you made my day :)
iltaf khalid

Yanıtlar:


68

Bir çözümün temel yapısı aşağıdaki gibidir:

  • Uygulamanın en son sürümünü (gerekirse) tekrar tekrar yüklemek ve başlatmaktan sorumlu bir ana döngü vardır.

  • Uygulama işini yapar, ancak indirme URL'sini periyodik olarak kontrol eder. Yeni bir sürüm tespit ederse, başlatıcıya geri döner.

Bunu gerçekleştirmenin birkaç yolu vardır. Örneğin:

  • Başlatıcı, değiştirilen bir JAR dosyasından uygulamayı çalıştırmak için yeni bir JVM başlatan bir sarmalayıcı komut dosyası veya ikili uygulama olabilir.

  • Başlatıcı, yeni JAR için bir sınıf yükleyici oluşturan, bir giriş noktası sınıfı yükleyen ve üzerinde bazı yöntemler çağıran bir Java uygulaması olabilir. Bu şekilde yaparsanız, sınıf yükleyici depolama sızıntılarına dikkat etmeniz gerekir, ancak bu zor değil. (Yalnızca JAR'dan yüklenen sınıflara sahip hiçbir nesnenin yeniden başlattıktan sonra erişilebilir olmadığından emin olmanız gerekir.)

Harici sarıcı yaklaşımının avantajları şunlardır:

  • sadece bir JAR'a ihtiyacınız var,
  • tüm Java uygulamasını değiştirebilirsiniz,
  • uygulama tarafından oluşturulan tüm ikincil iş parçacıkları, vb. özel kapatma mantığı olmadan ortadan kalkar ve
  • ayrıca uygulama çökmelerinden vb. kurtarma işlemlerini de yapabilirsiniz.

İkinci yaklaşım iki JAR gerektirir, ancak aşağıdaki avantajlara sahiptir:

  • çözüm saf Java ve taşınabilir,
  • geçiş daha hızlı olacak ve
  • yeniden başlatma sırasında durumu daha kolay koruyabilirsiniz (modulo sızıntısı sorunları).

"En iyi" yol, özel gereksinimlerinize bağlıdır.

Ayrıca şu hususlara da dikkat edilmelidir:

  • Otomatik güncellemede güvenlik riskleri vardır. Genel olarak, güncellemeleri sağlayan sunucu tehlikeye girerse veya güncellemeleri sağlayan mekanizmalar saldırıya açıksa, otomatik güncelleme istemcilerin tehlikeye atılmasına neden olabilir.

  • Müşteriye zarar verecek bir güncellemeyi müşteriye göndermek, yasal riskler ve işletmenizin itibarına yönelik riskler doğurabilir.


Tekerleği yeniden icat etmekten kaçınmanın bir yolunu bulursanız, bu iyi olur. Öneriler için diğer yanıtlara bakın.


43

Şu anda bir JAVA Linux Daemon geliştiriyorum ve ayrıca bir otomatik güncelleme mekanizması uygulama ihtiyacım vardı. Başvurumu bir jar dosyasıyla sınırlamak istedim ve basit bir çözüm buldum:

Güncelleyici uygulamasını güncellemenin kendisine paketleyin.

Uygulama : Uygulama daha yeni bir sürüm tespit ettiğinde şunları yapar:

  1. Güncellemeyi indir (Zipfile)
  2. Application and ApplicationUpdater'ı Çıkarın (tümü zip dosyasında)
  3. Güncelleyiciyi çalıştır

ApplicationUpdater : Güncelleyici çalıştığında şunları yapar:

  1. Uygulamayı durdurun (benim durumumda init.d aracılığıyla bir arka plan programı)
  2. Mevcut Uygulamanın üzerine yazmak için indirilen jar dosyasını kopyalayın
  3. Uygulamayı Başlatın
  4. Temizlemek.

Umarım birine yardımcı olur.


12

Bu bilinen bir sorundur ve bir tekerleği yeniden icat etmemenizi tavsiye ederim - kendi hackinizi yazmayın, sadece başkalarının yapmış olduğu şeyi kullanın.

Dikkate almanız gereken iki durum:

  1. Uygulamanın kendi kendine güncellenebilir olması ve güncelleme sırasında bile (sunucu uygulaması, gömülü uygulamalar) çalışmaya devam etmesi gerekir. OSGi ile gidin: Paketler veya Equinox p2 .

  2. Uygulama bir masaüstü uygulamasıdır ve bir yükleyiciye sahiptir. Güncelleme seçeneğine sahip birçok yükleyici var. Kurulumcu listesini kontrol edin .


12

Yakın zamanda Java 9'un modül sistemiyle tam uyumlu olan update4j'yi oluşturdum .

Yeniden başlatmadan yeni sürümü sorunsuz bir şekilde başlatacaktır.


Bir önyükleme / iş uygulama paradigması kullanarak. Önyükleme, iş uygulamasını yükler ve kaldırır ve genellikle güncellemeyi yapan önyüklemedir.
Mordechai

10

Çalışma zamanında eklentileri yükleyebilen ve bunları jEdit'teki benzer bir mekanizmadan esinlenerek hemen kullanmaya başlayabilen bir Java uygulaması yazdım. jEdit açık kaynak kodludur, bu nedenle nasıl çalıştığını görme seçeneğine sahipsiniz.

Çözüm, dosyaları jar'ten yüklemek için özel bir ClassLoader kullanır. Yüklendikten sonra, yeni kavanozdan, kendi mainyöntemi olarak işlev görecek bir yöntemi çağırabilirsiniz . Daha sonra zor kısım, eski koda yapılan tüm referanslardan kurtulmanızı sağlamaktır, böylece çöp toplanabilir. Bu konuda pek uzman değilim, işe yaradım ama kolay olmadı.


Java hakkında bilgim yok, ancak C #'da kodu açıkça kaldırmak için AppDomains'i kullanabilirsiniz. Belki Java'da da benzer bir kavram vardır.
Merlyn Morgan-Graham

1
Teşekkürler, gitmenin yolu bu gibi görünüyor. ClassLoaderNetworkClassLoader için JavaDoc'da
Jonas

Aynı JVM içinde statik değişkenlerle ilgili problemlerle mi karşılaştınız, yoksa kalıcı nesil? Bunların sınıf boşaltma ile ilgili sorunlar yaratabileceğini duydum.
ide

5
  1. İlk yol: tomcat'i kullanın ve dağıtım olanaklarını kullanın.
  2. İkinci yol: uygulamayı iki parçaya ayırmak (işlevsel ve güncel) ve güncelleme bölümünün işlev bölümünü değiştirmesine izin vermek.
  3. Üçüncü yol: Sunucu uygulamanızda sadece yeni sürümü indirin, ardından eski sürüm bağlı bağlantı noktasını serbest bırakır, ardından eski sürüm yeni sürümü çalıştırır (işlemi başlatır), ardından eski sürüm eski sürümü, eski sürümü silmek için yeni sürüme uygulama bağlantı noktasından bir istek gönderir sonlandırılır ve yeni sürüm eski sürümü siler. Bunun gibi: alternatif metin

İkinci yolunuz ilginç bir tasarım gibi görünüyor.
Jonas

2

Bu mutlaka en iyi yol değildir, ancak sizin için işe yarayabilir.

Bir önyükleme uygulaması yazabilirsiniz (WoW oynadıysanız, World of Warcraft başlatıcısı da olabilir). Bu önyükleme, güncellemeleri kontrol etmekten sorumludur.

  • Bir güncelleme mevcutsa, kullanıcıya sunacak, indirme, kurulum vb. İşlemleri gerçekleştirecektir.
  • Uygulama güncelse, kullanıcının uygulamayı başlatmasına izin verecektir.
  • İsteğe bağlı olarak, güncel olmasa bile kullanıcının uygulamayı başlatmasına izin verebilirsiniz.

Bu şekilde, başvurunuzdan çıkmaya zorlama konusunda endişelenmenize gerek kalmaz.

Uygulamanız web tabanlıysa ve güncel bir istemciye sahip olmaları önemliyse, uygulama çalışırken de sürüm kontrolleri yapabilirsiniz. Sunucuyla (bazı veya tüm aramalar) veya her ikisiyle normal iletişim gerçekleştirirken bunları aralıklarla yapabilirsiniz.

Yakın zamanda üzerinde çalıştığım bir ürün için, başlatma sırasında (bir önyükleyici uygulaması olmadan, ancak ana pencere görünmeden önce) ve sunucuya yapılan çağrılar sırasında sürüm kontrolleri yaptık. İstemci güncel olmadığında, kullanıcının manuel olarak çıkmasına güvendik, ancak sunucuya karşı herhangi bir eylemi yasakladık.

Lütfen, siz ana pencerenizi açmadan önce Java'nın UI kodunu çalıştırıp çalıştırmayacağını bilmediğimi unutmayın. C # / WPF kullanıyorduk.


Teşekkürler, bunu yapmanın güzel bir yolu. Ancak bu bir sunucu uygulamasıdır, dolayısıyla herhangi bir işlem yapabilecek bir kullanıcı yoktur. Ve bunun sadece tek bir jar dosyası olmasını tercih ederim, bu yüzden kullanıcı easyli tek bir jar dosyasını indirebilir ve başlangıçta başlatabilir, ancak ondan sonra hiçbir kullanıcı etkileşimi istemiyorum.
Jonas

"Sunucu uygulaması" dediğinizde, oturum açıldığında doğrudan sunucu üzerinde çalıştırılan bir uygulama mı demek istiyorsunuz?
Merlyn Morgan-Graham

@Jonas: .jar dosyalarının nasıl çalıştığını pek anlamıyorum, bu yüzden orada çok fazla hizmet edemiyorum. Java'ya özgü bir cevabı tercih edip etmediğinizi anlayabiliyorum. Umarım bu size en azından düşünmeniz için yiyecek verir :)
Merlyn Morgan-Graham

@Merlyn: Fikirlerinizi paylaştığınız için minnettarım. Evet, bu bir Linux sunucusunda çalışan bir Java uygulamasıdır ve bu sunucuda kimse oturum açmaz.
Jonas

1
@Jonas: Bunu daha önce düşünmediğinizden değil, ama - Gördüğüm çoğu web hizmetinin manuel bir dağıtım stratejisi var. Güncellemeleri nasıl kontrol ettiğiniz konusunda dikkatli olmak isteyebilirsiniz. Hatalı / bozuk kodu iterseniz veya çok dosyalı bir dağıtımla yalnızca kısmen yapılırsa, sunucu kendini güncellemeye çalışabilir ve ardından bozuk bir sunucunuz olur.
Merlyn Morgan-Graham

2

Uygulamanızı Equinox eklentilerini kullanarak oluşturursanız, bu soruna hazır bir çözüm bulmak için P2 Provisioning System'ı kullanabilirsiniz. Bu, sunucunun bir güncellemeden sonra kendini yeniden başlatmasını gerektirecektir.


1

Yeni bir kavanoz (vb.) İndirirken bir güvenlik sorunu görüyorum, örneğin orta saldırıda bir adam. Her zaman indirilebilir güncellemenizi imzalamanız gerekir.

JAX2015'te Adam Bien, ikili dosyaları güncellemek için JGit'i kullanmaktan bahsetti. Maalesef herhangi bir ders bulamadım.

Almanca kaynak.

Adam Bien güncelleyiciyi yarattı, buraya bakın

Bunu çatallı burada bazı JavaFX kullanıcı arabirimi ile. Ayrıca otomatik bir imzalama üzerinde de çalışıyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.