Java'da System.exit'i ne zaman çağırmalıyız


193

Java'da, System.exit(0)aşağıdaki koddaki veya olmayan kod arasındaki fark nedir ?

public class TestExit
{      
    public static void main(String[] args)
    { 
        System.out.println("hello world");

        System.exit(0);  // is it necessary? And when it must be called? 
    }      
}

Belge diyor ki: "Bu yöntem normalde asla geri gelmez." Bu ne demek?

Yanıtlar:


207

System.exit()program kapanmadan önce kapatma kancalarını çalıştırmak için kullanılabilir . Bu, programın tüm bölümlerinin birbirinin farkında olamadığı (ve olmaması gerektiği) daha büyük programlarda kapatmayı ele almanın kullanışlı bir yoludur. Daha sonra, biri istifa etmek isterse, sadece arayabilir System.exit()ve kapatma kancaları (uygun şekilde ayarlanmışsa) dosyaları kapatma, kaynakları serbest bırakma gibi gerekli tüm kapatma törenlerini yapmaya özen gösterir.

"Bu yöntem asla normal şekilde geri dönmez." sadece yöntemin geri dönmeyeceği anlamına gelir; bir iplik oraya gittiğinde, geri gelmeyecektir.

Bir programdan çıkmanın bir diğer belki de daha yaygın yolu, mainyöntemin sonuna ulaşmaktır . Ancak, çalışan daemon olmayan iş parçacıkları varsa, bunlar kapatılmaz ve bu nedenle JVM çıkmaz. Böylece, böyle bir daemon olmayan iş parçacığınız varsa, tüm daemon olmayan iş parçacıklarını kapatmak ve diğer kaynakları serbest bırakmak için başka yollara (kapatma kancaları dışında) ihtiyacınız vardır. Başka daemon olmayan iş parçacıkları mainyoksa, JVM kapatılır ve kapatma kancaları çağrılır.

Herhangi bir nedenle kapatma kancaları değersiz ve yanlış anlaşılmış bir mekanizma gibi görünüyor ve insanlar tekerleği programlarından çıkmak için her türlü özel özel hack'le yeniden icat ediyorlar. Kapatma kancalarının kullanılmasını teşvik ederim; yine de kullanacağınız standart Çalışma Süresinde hepsi orada .


10
"Bu yöntem asla normal şekilde geri dönmez." sadece yöntemin geri dönmeyeceği anlamına gelir; bir iplik oraya gittiğinde, geri gelmeyecektir. Özellikle bunun System.exit (0) çağrısı yapan bir yöntemi test edemeyeceğiniz anlamına geldiğine dikkat edin ...
Bill Michell

5
-1 Yanlış. System.exit veya main () öğesinin sonlandırılmasından bağımsız olarak, JVM normal olarak sonlanırsa kapatma kancaları çalışır. Bkz. Zx81 / doku / java / javadoc / j2se1.5.0 / docs / api / java / lang /…
sleske

31
@sleske: Etrafında başka daemon olmayan iş parçacıkları varsa main () öğesinin sonlandırılması yeterli olmaz. Sistem.exit () öğesini açıkça çağırmazsanız, kapatma yalnızca arka plan olmayan son iş parçacığı sonlandırıldıktan sonra başlatılır. Bu, Çalışma Zamanı belgelerinde açıkça belirtilmiştir.
Joonas Pulakka

3
Kapatma kancanız sırayla System.exit adlı iş parçacığına dayanıyorsa, kilitleneceğinizi unutmayın.
djechlin

8
Eklenecek bir şey, birisi bir çalışma zamanını durdurursa, kapatma kancaları çalışmaz ( Runtime.getRuntime().halt())
Rogue

50

Bu durumda, gerekli değildir. Fazladan iş parçacığı başlatılmayacak, çıkış kodunu değiştirmiyorsunuz (varsayılan olarak 0'dır) - temelde anlamsızdır.

Dokümanlar yöntemin asla normal şekilde geri dönmediğini söylediğinde , derleyici bilmiyor olsa bile , sonraki kod satırına etkin bir şekilde erişilemez demektir :

System.exit(0);
System.out.println("This line will never be reached");

Bir istisna atılır veya VM geri dönmeden önce sona erer. Asla "sadece geri döner".

System.exit()IME demeye değer olmak çok nadirdir . Bir komut satırı aracı yazıyorsanız mantıklı olabilir ve sadece bir istisna atmak yerine çıkış kodu aracılığıyla bir hata belirtmek istiyorsanız ... ama normal üretim kodunda son kullandığımı hatırlayamıyorum .


2
Derleyici bunu neden bilmiyor? System.exit () belirli algılama kodunu garanti edecek kadar özel değil mi?
Bart van Heukelom

3
@Bart: Hayır, sanmıyorum. Bu gibi şeyler için dile özel durumlar koymak, dil karmaşıklığına çok az fayda sağlar.
Jon Skeet

Ben "asla normal döner" ifadesinin "ani tamamlanması" ile ilgili olduğunu düşündüm. (JLS bölüm 14.1). Yanlış mıyım?
aioobe

@aioobe: Hayır, haklısın. System.exit()asla normal şekilde tamamlanmayacaktır - her zaman bir istisna veya VM'nin kapatılmasıyla (gerçekten JLS'de kapsanmaz) tamamlanır.
Jon Skeet

1
@piechuckerr: Sana bunu düşündüren nedir? Programın bir hatayla karşılaştığını çağıran kabuğa (veya her neyse) belirtmek için 0 dışında bir değerle çağırmak tamamen mantıklıdır.
Jon Skeet

15

System.exit(0)JVM'yi sonlandırır. Bunun gibi basit örneklerde farkı algılamak zordur. Parametre işletim sistemine geri aktarılır ve normal olarak anormal sonlandırmayı belirtmek için kullanılır (örn. Bir tür ölümcül hata), bu yüzden bir toplu iş dosyasından veya kabuk komut dosyasından java çağırırsanız bu değeri alabilir ve bir fikir edinebilirsiniz. uygulama başarılı olursa.

System.exit(0)Bir uygulama sunucusuna dağıtılmış bir uygulamayı çağırırsanız oldukça etkili olur (denemeden önce düşünün).


15

Bu yöntem asla dönmez, çünkü bu dünyanın sonu ve kodunuzun hiçbiri daha sonra yürütülmeyecektir.

Örneğin, uygulamanız kodda aynı noktada yine de çıkacaktır, ancak System.exit kullanıyorsanız. mesela örneğin çevreye özel bir kod döndürme seçeneğiniz var

System.exit(42);

Çıkış kodunuzu kim kullanacak? Uygulamayı çağıran bir komut dosyası. Windows, Unix ve diğer tüm yazılabilir ortamlarda çalışır.

Neden bir kod döndürülmeli? "Başarılı olamadım", "Veritabanı cevap vermedi" gibi şeyler söylemek için.

Bir çıkış kodunun değerini nasıl alacağınızı ve bunu bir unix kabuk komut dosyasında veya windows cmd komut dosyasında nasıl kullanacağınızı görmek için bu yanıtı bu sitede kontrol edebilirsiniz.


12

Karmaşık kapatma kancalarına sahip olabilecek uygulamalarda, bu yöntem bilinmeyen bir iş parçacığından çağrılmamalıdır. System.exitJVM sonlanıncaya kadar çağrı engelleneceğinden asla normal şekilde çıkılmaz. Sanki bitmeden önce fişi takılı olan her hangi kod çalışıyorsa. Arama System.exit, programın kapatma kancalarını başlatır ve System.exitprogramın sonlandırılmasına kadar çağıran tüm evreler engellenir. Bu, kapatma kancası sırayla System.exitçağrılan iş parçacığına bir görev gönderirse , programın kilitleneceği anlamına gelir.

Aşağıdaki kod ile bu işliyorum:

public static void exit(final int status) {
    new Thread("App-exit") {
        @Override
        public void run() {
            System.exit(status);
        }
    }.start();
}

Ayrıca System.exit aslında JVM sona ermeyecek bir sorun vardı. Ancak sadece belirli koşullar altında oldu. Aldığım bir iş parçacığı bana hangi iş parçacığı / kapatma işleyicileri kapatma engelleme hakkında herhangi bir fikir vermedi. Yorumda açıklanan kodu kullanmak çözmemde bana yardımcı oldu!
Kai

7

Ama cevap gerçekten yardımcı oldu ama bazı nasıl biraz daha fazla ayrıntı kaçırdı. Umarım aşağıdaki cevaba ek olarak java'daki kapatma işlemini anlamaya yardımcı olur:

  1. Düzenli bir * kapanmada, JVM önce tüm kayıtlı kapatma kancalarını başlatır. Kapatma kancaları, Runtime.addShutdownHook'a kaydedilen yıldızlanmamış evrelerdir.
  2. JVM, kapatma kancalarının başlatıldığı sırada hiçbir garanti vermez. Herhangi bir uygulama iş parçacığı (daemon veya daemon olmayan) kapatma zamanında hala çalışıyorsa , kapatma işlemiyle aynı anda çalışmaya devam ederler .
  3. Tüm kapatma kancaları tamamlandığında, JFM, runFinalizersOnExit doğruysa sonlandırıcıları çalıştırmayı seçebilir ve ardından durur.
  4. JVM, kapanma zamanında çalışmakta olan uygulama iş parçacıklarını durdurma veya kesme girişiminde bulunmaz; JVM sonunda durduğunda aniden feshedilir.
  5. Kapatma kancaları veya sonlandırıcıları tamamlanmazsa, düzenli kapatma işlemi “askıda kalır” ve JVM aniden kapatılmalıdır.
  6. Ani bir kapanmada, JVM'nin JVM'yi durdurmak dışında bir şey yapması gerekmez; kapatma kancaları çalışmaz.

Not: JVM düzenli veya aniden kapanabilir .

  1. Son “normal” (veri olmayan) iş parçacığı sona erdiğinde, birisi System.exit'i çağırdığında veya platforma özgü diğer yollarla (SIGINT gönderme veya Ctrl-C'ye vurma gibi) düzenli bir kapatma başlatılır.
  2. Yukarıda JVM'nin kapanması için standart ve tercih edilen yol olsa da, Runtime.halt'ı arayarak veya işletim sistemi aracılığıyla JVM işlemini öldürerek (SIGKILL göndermek gibi) aniden kapatılabilir.

7

System.exit(0)Bu sebepleri ASLA çağırmamalısınız :

  1. Gizli bir "git" ve "git" kontrol akışını bozar. Bu bağlamda kancalara güvenmek, takımdaki her geliştiricinin bilmesi gereken zihinsel bir haritadır.
  2. "Normalde" programdan çıkmak, işletim sistemine System.exit(0)gereksiz olduğu için aynı çıkış kodunu sağlar .

    Programınız "normal" durumdan çıkamazsa, geliştirme [tasarım] kontrolünü kaybedersiniz. Sistem durumu üzerinde her zaman tam denetime sahip olmalısınız.

  3. Durdurulamayan iş parçacıklarını çalıştırma gibi programlama sorunları normalde gizlenir.
  4. İş parçacıklarını anormal şekilde kesintiye uğratan tutarsız bir uygulama durumu ile karşılaşabilirsiniz. (Bakınız # 3)

Bu arada: Anormal program sonlandırmasını belirtmek istiyorsanız, 0'dan başka dönüş kodlarının döndürülmesi mantıklıdır.


2
"Sistem durumu üzerinde her zaman tam kontrol sahibi olmalısınız." Java ile bu mümkün değildir. IoC çerçeveleri ve uygulama sunucuları, sistem durumu kontrolünden vazgeçmenin sadece 2 çok popüler ve yaygın olarak kullanılan yoludur. Ve bu tamamen iyi.
mhlz

Lütfen uygulama sunucunuzda System.exit (0) komutunu çalıştırın ve bana sunucu yöneticinizin tepkilerini anlatın ... Bu sorunun konusunu ve cevabımı kaçırdınız.
oopexpert

Belki yeterince açık değildim. Sorumlu olduğunuz sistem durumu üzerinde her zaman tam denetime sahip olmalısınız. Evet, bazı sorumluluklar uygulama sunucularına ve IoC'ye aktarıldı. Ama bundan bahsetmiyordum.
oopexpert

5

System.exit gerekli

  • 0 olmayan bir hata kodu döndürmek istediğinizde
  • programınızdan ana olmayan bir yerden çıkmak istediğinizde ()

Sizin durumunuzda, basit ana dönüş ile aynı şeyi yapar.


İkincisi ile ne demek istiyorsun? Programı kapatmanın doğru yolu, tüm evreleri (güzel) durdurmaktır, ana iş parçacığından başlatılması gerekmeyen bir harekettir, bu yüzden exittek seçeneğiniz bu değildir.
Bart van Heukelom

@Bart: Açıkladığınız şey , doğru yolu değil , bir programı kapatmanın olası yollarından biridir . Tüm iplikleri güzelce durdurmak için kapatma kancalarını kullanmanın yanlış bir yanı yoktur. Ve kapatma kancaları ile başlatılır . Tek seçenek değil, ama kesinlikle dikkate değer bir seçenek. exit
Joonas Pulakka

Ancak dokümanlardan topladığım şey, kapatma kancaları çok hassas ve yapmasını istediğiniz şeyi yapmak için çok zamanınız olmayabilir. Elbette, bir işletim sistemi kapatma veya bir şey durumunda güzel bir şekilde çıkmak için kullanın, ancak System.exit () 'i kendiniz çağıracaksanız, kapatma kodunu ondan önce yapmanın daha iyi olduğunu düşünüyorum (bundan sonra muhtemelen System.exit () artık gerek yok)
Bart van Heukelom 15:10

1
Kapatma kancaları bitirmek için her zaman var. VM tüm kancalar geri dönmeden durdurulmaz. Yürütülmesi çok uzun süren bir kapatma kancası kaydederek VM'nin çıkmasını önlemek gerçekten de mümkündür. Ancak elbette kapatma sırasını çeşitli, alternatif yollarla yapmak mümkündür.
Joonas Pulakka

Başka daemon olmayan iş parçacıkları varsa ana ekrandan dönme kapanmaz.
djechlin

4

Java Language Specification diyor ki

Program Çıkışı

Bir program tüm etkinliğini sonlandırır ve iki şeyden biri gerçekleştiğinde çıkar:

Daemon thread olmayan tüm evreler sona erer.

Bazı iş parçacığı Runtime veya class System sınıfının çıkış yöntemini çağırır ve çıkış işlemi güvenlik yöneticisi tarafından yasaklanmaz.

Bu, büyük bir programınız olduğunda (bundan daha büyük olsa da) ve yürütülmesini bitirmek istediğinizde kullanmanız gerektiği anlamına gelir.


3

JVM'de çalışan başka bir programınız varsa ve System.exit kullanıyorsanız, bu ikinci program da kapatılacaktır. Örneğin, bir küme düğümünde bir java işi çalıştırdığınızı ve küme düğümünü yöneten java programının aynı JVM'de çalıştığını düşünün. İş System.exit kullanacaksa, yalnızca işten çıkmakla kalmaz, aynı zamanda "tüm düğümü kapatır". Yönetim programı yanlışlıkla kapatıldığından, bu küme düğümüne başka bir iş gönderemezsiniz.

Bu nedenle, programınızı aynı JVM içindeki başka bir java programından denetlemek istiyorsanız System.exit komutunu kullanmayın.

Tüm JVM'yi bilerek kapatmak istiyorsanız ve diğer yanıtlarda açıklanan olasılıklardan yararlanmak istiyorsanız (örn. Kapatma kancaları: Java kapatma kancası , komut satırı için sıfır olmayan dönüş değeri) System.exit komutunu kullanın. call: Windows toplu iş dosyasında bir Java programının çıkış durumu nasıl alınır ).

Ayrıca Çalışma Zamanı İstisnalarına bir göz atın: System.exit (num) veya anadan bir RuntimeException mı?

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.