JVM이 메인 메소드에 의해 발생 된 예외를 어떻게 처리합니까?


10

예외를 이해하고, 던지고, 처리하고, 호출 스택의 하위 메소드 (예 :)로 전파하는 것을 이해합니다 throws.

내가 이해하지 못하는 것은 이것입니다 :

public static void main(String[] args) throws Exception {
    ...
}

지금, 나는 가정 하는 경우에 것을 main을 던져 Exception, JVM이 그것을 처리 (맞습니까?). 이 경우 내 질문은 다음과 같습니다.

JVM은 예외를 어떻게 처리 main합니까? 무엇을합니까?

답변:


19

public static void mainJava 의 메소드 나 mainC 의 함수는 프로그램의 실제 진입 점 이라고 생각할 수 있지만 그렇지 않습니다. 모든 고급 언어 (C 포함)에는 프로그램을 초기화 한 다음 제어 흐름을 진입 점으로 전송하는 언어 런타임이 있습니다. Java의 경우 초기화에는 다음이 포함됩니다.

  • JVM 설정
  • 필요한 클래스 로딩
  • 정적 초기화 블록을 실행합니다. 이를 main호출 하기 전에 사용자 정의 코드를 실행할 수 있습니다 . 이 블록들은 예외를 던져서는 안됩니다.

예외 처리를 구현하는 다양한 방법이 있지만이 질문의 목적을 위해 모두 블랙 박스로 볼 수 있습니다. 그러나 중요한 점은 언어 런타임이 항상 사용자 코드에 의해 포착되지 않은 모든 예외를 포착하는 가장 바깥 쪽 예외 처리기를 제공해야한다는 것입니다. 이 예외 처리기는 일반적으로 스택 추적을 인쇄하고 프로그램을 순서대로 종료 한 다음 오류 코드로 종료됩니다. 프로그램을 올바르게 종료하는 것은 객체 그래프 파괴, 종료 자 호출 및 메모리, 파일 핸들 또는 네트워크 연결과 같은 리소스 해제를 포함합니다.

설명을 위해 모든 코드를 다음과 같은 거대한 try-catch로 래핑하는 런타임을 이미징 할 수 있습니다.

try {
    loadClasses();
    runInitializers();
    main(argv);
    System.exit(0);
} catch (Throwable e) {
    e.printStackTrace();
    System.exit(-1);
}

언어가 실제로 이와 같은 코드를 실행할 필요는 없다는 점을 제외하고. throw첫 번째 적용 가능한 예외 처리기를 검색 하는 코드 (또는 이와 동등한 것) 에서 동일한 의미가 구현 될 수 있습니다 .


9

모든 Java 코드는 스레드 컨텍스트에서 실행됩니다 . 링크 된 JavaDoc은 오류 처리 및 종료 기준을 설명하지만 그 요점은 다음과 같습니다.

  • JVM이 자체적으로 가동되어 실행 환경을 준비합니다.
  • JVM main()은 적용 가능한 명령 행 매개 변수를 사용 하여 메소드를 실행할 스레드를 작성합니다 .
  • JVM은 예외를 표준 오류로 인쇄하고 종료하는 기본 포착되지 않은 예외 핸들러를 설정합니다.
  • JVM이 스레드를 실행합니다.

포착되지 않은 예외의 경우 프로그램은 위의 세 번째 항목에 따라 효과적으로 종료됩니다. 이 동작은 Java 언어 사양 섹션 11.3에 자세히 설명되어 있습니다.


추가 정보

다른 사람들은 정적 블록과 이전에 실행되는 방법을 언급했습니다 main(). 그러나 이것은 올바르게 이해하기 위해 약간의 설명이 필요합니다.

클래스를로드 할 때 클래스 로더는 클래스를 인스턴스화 하기 위해 클래스를 사용 하기 전에 모든 static final상태 를 초기화하고 모든 static블록을 실행 해야합니다 (제외 : 클래스 상수가 생성 된 정적 블록에서 초기화되는 Java 클래스 만들기 클래스의 인스턴스와 생성자가 상수를 참조합니다. Boom!). 그러나 이것은 모든 코드가 클래스를 참조하기 전에 클래스 로더 로직에서 발생 합니다 . 또한 클래스는 클래스를 참조하는 모든 스레드에로드됩니다.

이것은 포함하는 클래스가 main()다른 클래스 (예 : 클래스 상수)를 참조 하는 경우 정적 블록을 포함하도록 실행하기 전에 해당 클래스 로드 해야합니다main() . 그렇지 않으면 정적 블록이 위와 같이 실행됩니다. 클래스가로드 main()되지 않으면 포함하는 클래스 도로드되지 않고 프로그램이 종료됩니다.

또 다른 참고 : 정적 블록이 발생할 수 있습니다 . Errors있는 그대로 던져집니다. Exceptions금지되어 있습니다 (컴파일 타임 오류). ExceptionInInitializerErrorRuntimeExceptions 에 랩됩니다 . 이들은 잡히지 않은 예외 처리기마다 처리되며, 클래스 참조 (및로드)를주의해서 -에 래핑하지 않으면 일반적으로 스레드 또는 응용 프로그램 (주 스레드)을 강제 종료합니다 .trycatch

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.