101

마지막으로 자바에서 실행되지 않을 수있는 조건이 있습니까? 감사.


  • 특정 잘 알려진 회사에서 취업하려고 할 때 묻는 질문입니까? - Tom Hawtin - tackline
  • @ TomHawtin-tackline 케어 이름은? (하느님, 나는이 지위가 얼마나 오래 되었습니까!) - Hele
  • @Hele 게임을 멀리하고 싶지는 않지만 Google로 넘어갈 수 있습니다. - Tom Hawtin - tackline

12 답변


127

~로부터썬 튜토리얼

참고 : try가 실행되는 동안 JVM이 종료되면   또는 catch 코드가 실행되고 있으면   finally 블록은 실행되지 않을 수 있습니다.   마찬가지로, 스레드를 실행하는 스레드가   코드를 시도하거나 catch하는 것이 중단되거나   살해 당했다.   응용 프로그램을   전체가 계속됩니다.

마침내 블록이 실행되지 않는 다른 방법에 대해서는 모른다.


  • @dhiller - & quot; 전원 끄기 & quot; & quot; JVM이 종료 된 경우 ... & quot;에 포함됩니다. :-피 - Jason Coco
  • @ 제이슨 코코 : 종료 (권력의 상실과 마찬가지로) 종료로 꽤 똑같은 것은 아닙니다; 후자는 전자에서 절정에 달하는 다소 조직 된 과정이다. ;피 - user359996
  • AFAIK, 스레드가 인터럽트되면 즉시 멈추지 않습니다. 인터럽트를 감지하고 작업을 중지하기 위해 스레드의 코드가 있으므로 결국 코드가 실행되어야합니다. - Bart van Heukelom
  • finally 블록에 예외가 발생하면 나머지 블록은 실행되지 않습니다. - Adriaan Koster
  • 잘 그거야! - eiran

58

System.exit가상 시스템을 종료합니다.

현재 실행중인 Java를 종료합니다.   가상 기기. 인수가 제공됩니다.   상태 코드로; 관례 상,   0이 아닌 상태 코드가 비정상임을 나타냅니다.   종료.

이 메소드는exit방법   수업Runtime. 이 방법은 결코   정상적으로 돌아옵니다.

    try {
        System.out.println("hello");
        System.exit(0);
    }
    finally {
        System.out.println("bye");
    } // try-finally

"bye"는 위 코드에서 인쇄하지 않습니다.


  • 또한 예외는 JVM (Java Virtual Machine)을 종료해야합니다. - kaissun
  • System.exit (0)을 실행하는 동안 예외가 발생하면 finally 블록이 실행됩니다. - halil

47

다른 사람들이 말한 것을 확장하기 만하면 JVM이 종료되는 것과 같은 일을 일으키지 않는 것이 finally 블록을 초래할 것입니다. 그래서 다음과 같은 방법 :

public static int Stupid() {
  try {
    return 0;
  }
  finally {
    return 1;
  }
}

이상하게도 컴파일하고 반환합니다.


  • 이것은 몇 주 후에 몇 시간 동안 나에게 정말로 혼란 스러웠다. - nickf
  • finally 블록에서 값을 반환하는 것은 좋지 않은 아이디어로 간주됩니다. try 블록에서만 리턴하거나 try / finally 블록 외부에서 리턴하십시오. 대부분의 IDE는 이것을 경고로 표시합니다. - Ran Biron
  • @nickf 나는 당신이 더 이상 혼란스럽지 않다는 것을 모았습니다. 왜 1이 반환되고 0이 아닌지에 대해 자세히 설명해 주시겠습니까? 처음에는 0을 유지하는 함수의 반환 값을 저장하는 메모리 (또는 레지스터)는 finally 블록이 실행될 때 덮어 씁니다 . - Yaneeve
  • 궁금 해서요. C #에서는 finally 블록에서 돌아올 수 없습니다. - JMCF125
  • @ 랜비론 물론. 실제로 finally 블록 내부로 돌아가라고 권유하지는 않았지만 return 문도 여전히 해당 블록의 코드를 실행하게한다는 것을 입증하려고했습니다. - Aquarelle

14

System.exit과 관련하여 finally 블록이 실행되지 않을 수도있는 치명적인 오류 유형도 있습니다. JVM의 메모리가 완전히 소모되면 catch 나 finally없이 종료 될 수 있습니다.

특히, 나는 우리가 어리석게도 사용하려고했던 프로젝트를 기억한다.

catch (OutOfMemoryError oome) {
    // do stuff
}

JVM에 catch 블록을 실행하기위한 메모리가 남아 있지 않기 때문에 작동하지 않습니다.


  • OutOfMemoryError가 발생하면 대개 메모리가 남아 있습니다 (GC 스래 싱을 중지하기 위해). 그러나 반복해서 잡으면 분명히 GC 스 래싱으로 돌아갈 것입니다. - Tom Hawtin - tackline
  • 나는 체크되지 않은 예외를 잡아서는 안된다고 생각했습니다! - Sergii Shevchyk
  • 내 편에서 jdk7을 사용하여 시도했지만 OutOfMemory 오류가 발생했습니다! - Jaskey

9

try { for (;;); } finally { System.err.println("?"); }

이 경우 마침내 실행되지 않습니다 (단,Thread.stop도구 인터페이스를 통해 등가라고합니다).


  • 이 페이지에서는 ThreadDeath 오류가 throw되고 Thread.stop ()이 호출 될 때 스택이 정상적으로 풀린다 고 주장합니다. 내가 놓친 캐치가 있습니까?download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/guide/… - spurserh
  • 나는 그럴 수 없다고 생각합니다. 어쩌면 거기에없는 잡기를 상상할 수도 있습니다. 우리가 명시 적으로throw, 그 다음에finally블록이 예상대로 실행됩니다.try { throw new ThreadDeath(); } finally { System.err.println("?"); } - Tom Hawtin - tackline

7

Sun의 튜토리얼은,이 thread로 잘못 인용되고 있습니다.

참고 : try 또는 catch 코드가 실행되는 동안 JVM이 종료되면 finally 블록의지실행되지 않습니다. 마찬가지로 try 또는 catch 코드를 실행하는 스레드가 인터럽트되거나 죽는 경우 finally 블록의지응용 프로그램 전체가 계속 실행 되더라도 실행되지 않습니다.

마침내 차단을 위해 태양 튜토리얼을 들여다 보면 "실행되지 않을 것"이라고 말하지는 않지만 "실행하지 않을 수 있습니다" 다음은 올바른 설명입니다.

참고 : try 또는 catch 코드가 실행되는 동안 JVM이 종료되면 finally 블록할 수있다실행되지 않습니다. 마찬가지로 try 또는 catch 코드를 실행하는 스레드가 인터럽트되거나 죽는 경우 finally 블록할 수있다응용 프로그램 전체가 계속 실행 되더라도 실행되지 않습니다.

이 동작의 명백한 이유는 system.exit ()에 대한 호출이 런타임 시스템 스레드에서 처리되기 때문에 jvm을 종료하는 데 시간이 걸릴 수 있습니다. 스레드 스케줄러는 마침내 실행을 요청할 수 있습니다. 마지막으로 항상 실행되도록 설계되었지만 jvm을 종료하는 경우 jvm이 마침내 실행되기 전에 종료 될 수 있습니다.


5

또한 교착 상태 / 라이브 록이 내부에서 발생하는 경우try블록.

다음은이를 보여주는 코드입니다.

public class DeadLocker {
    private static class SampleRunnable implements Runnable {
        private String threadId;
        private Object lock1;
        private Object lock2;

        public SampleRunnable(String threadId, Object lock1, Object lock2) {
            super();
            this.threadId = threadId;
            this.lock1 = lock1;
            this.lock2 = lock2;
        }

        @Override
        public void run() {
            try {
                synchronized (lock1) {
                    System.out.println(threadId + " inside lock1");
                    Thread.sleep(1000);
                    synchronized (lock2) {
                        System.out.println(threadId + " inside lock2");
                    }
                }
            } catch (Exception e) {
            } finally {
                System.out.println("finally");
            }
        }

    }

    public static void main(String[] args) throws Exception {
        Object ob1 = new Object();
        Object ob2 = new Object();
        Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2));
        Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1));
        t1.start();
        t2.start();
    }
}

이 코드는 다음과 같은 출력을 생성합니다.

t1 inside lock1
t2 inside lock1

"마침내"인쇄되지 않음


  • 기술적으로 try 블록은 결코 종료되지 않으므로 finally 블록은 절대로 실행될 기회가 없어야합니다. 무한 루프에 대해서도 마찬가지입니다. - Jeff Mercado

4

다음은 finally 블록을 우회 할 수있는 몇 가지 조건입니다.

  1. try 또는 catch 코드가 실행되는 동안 JVM이 종료되면 finally 블록이 실행되지 않을 수 있습니다.
  2. 정상 종료 - 이것은 마지막 비 데몬 스레드가 종료되거나 Runtime.exit ()가 종료 될 때 발생합니다.
  3. 스레드가 종료되면 JVM은 실행중인 스레드의 인벤토리를 수행하고 남아있는 유일한 스레드가 데몬 스레드 인 경우 순서대로 종료를 시작합니다. JVM이 정지하고 남아있는 모든 데몬 쓰레드가 버려지면 finally 블록이 실행되지 않고 스택이 풀리고 JVM이 종료됩니다. 데몬 스레드는 드물게 사용되어야하며 정리 작업없이 언제든지 안전하게 버려 질 수있는 처리 작업은 거의 없습니다. 특히, 모든 종류의 I / O를 수행 할 수있는 작업에 데몬 스레드를 사용하는 것은 위험합니다. 데몬 스레드는 인 메모리 캐시에서 만료 된 항목을 주기적으로 제거하는 백그라운드 스레드와 같은 "하우스 키핑"작업에 가장 잘 저장됩니다.

마지막 비 데몬 스레드 종료 예 :

public class TestDaemon {
    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("Is alive");
                    Thread.sleep(10);
                    // throw new RuntimeException();
                }
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                System.out.println("This will never be executed.");
            }
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread daemon = new Thread(runnable);
        daemon.setDaemon(true);
        daemon.start();
        Thread.sleep(100);
        // daemon.stop();
        System.out.println("Last non-daemon thread exits.");
    }
}

산출:

Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive


0

play 프레임 워크와 관련하여 구체적으로 실행하지 않는 finally 블록의 매우 구체적인 경우를 보았습니다.

나는이 컨트롤러 액션 코드의 finally 블록이 Exception 후에 만 호출되었지만 호출이 실제로 성공했을 때 결코 호출되지 않았다는 것에 놀랐다.

try {
    InputStream is = getInputStreamMethod();
    renderBinary(is, "out.zip");
catch (Exception e) {
    e.printStackTrace();
} finally {
    cleanUp();
}

renderBinary ()가 호출 될 때 스레드가 종료되었거나 무언가가되었습니다. 나는 다른 render () 호출에 대해서도 같은 일이 일어날 것이라고 생각하지만, 그것을 검증하지는 않았다.

try / catch 후에 renderBinary ()를 이동하여 문제를 해결했습니다. 추가 조사를 통해 play는 컨트롤러 액션이 실행 된 후에 실행되는 메서드를 만들기위한 @Finally 주석을 제공한다는 것을 알 수있었습니다. 여기서주의해야 할 점은 컨트롤러에서 ANY 액션을 실행 한 후에 호출된다는 것이므로 항상 좋은 선택이 아닐 수 있습니다.


0

다음과 같은 경우에는 finally 블록이 실행되지 않습니다.

  • 언제System.exit(0)~에서 호출 됨try블록.
  • JVM의 메모리가 부족한 경우
  • java 프로세스가 작업 mgr 또는 console에서 강제 종료 될 때
  • 교착 상태try블록
  • 정전으로 기계가 꺼질 때

마침내 블록이 실행되지 않는 다른 프린지 케이스도있을 수 있습니다.


0

finally 블록 코드 실행을 중지하는 방법에는 두 가지가 있습니다.

1. System.exit ();을 사용하십시오.

2. 어떻게 든 실행 제어가 블록에 도달하지 못하면.

만나다:

public class Main
{
  public static void main (String[]args)
  {
    if(true){
        System.out.println("will exceute");
    }else{
        try{
            System.out.println("result = "+5/0);
        }catch(ArithmeticException e){
          System.out.println("will not exceute");
        }finally{
          System.out.println("will not exceute");  
        }
    }
  }
}


-1

//If ArithmeticException Occur Inner finally would not be executed
class Temp
{
    public static void main(String[] s)
    {
        try
        {
        int x = 10/s.length;
        System.out.println(x);
        try
            {
                int z[] = new int[s.length];
                z[10] = 1000;
            }catch(ArrayIndexOutOfBoundsException e)
            {
                System.out.println(e);
            }
         finally
        {
            System.out.println("Inner finally");
        }
        }
        catch(ArithmeticException e)
        {
            System.out.println(e);
        }
    finally 
    {
        System.out.println("Outer Finally"); 
    }

System.out.println("Remaining Code");   
}
}


  • 들여 쓰기를 개선하고 세부 사항을 추가하십시오. - ROMANIA_engineer
  • 실행은 심지어 내부 try 블록에 도착하지 않을 것입니다. 물론 내부는 결국 실행되지 않습니다. - Anton Arhipov

연결된 질문


관련된 질문

최근 질문