javafinally 블록 실행 시기 전면 분석

4715 단어 javafinally실행
자바에서finally 키워드는 일반적으로trycatch 블록과 함께 사용됩니다.방법이 끝나기 전이나 이상이 발생했을 때 자원 방출을 하는 데 사용됩니다.최근에도 인터넷에trycatchfinally 키워드가 실행되는 순서를 논의하는 글이 올라왔고finally 블록은 방법이 마지막에 실행된다는 것을 제시했다.
이러한 관점은 보편적으로 다음과 같다.
1)finally 키워드는 프로그램return 문장 뒤에 이전 단계로 되돌아가기 전에 실행됩니다. 그 중에서 되돌아오는 값은 임시 구역에 저장되고finally 블록의 부분을 실행한 후에 임시 구역의 값을 되돌려줍니다.
2) finally 블록에 반환 값이 있으면 프로그램 앞의try나catch 블록에return 문장이 임시 구역에 저장된 값을 대체합니다.
그러나 문제는 정말 이렇습니까? 우리가 자세히 생각해 보면 jvm는 실행할 때 바이트 명령에 대해 해석하고 실행합니다. 만약에return 문장을 실행한 후에 그 뒤에 finally 블록이 있는지 없는지 어떻게 알 수 있습니까? 만약에finally 블록이 없으면 어떻게 합니까? 바이트 명령이든 컴퓨터의 명령이든 명확해야 합니다. jvm는 그렇게 지능적이지 않습니다. 같은 명령은 명확해야 합니다. 두 가지 의미를 포함하지 않습니다.따라서return 문장이 실행될 때 어떤 경우에도 창고의 내용을 통일하여 호출 방법으로 되돌려줍니다.
이와 동시에 우리는 이라는 책에서 또 다른 해석을 제시한 것을 볼 수 있다.자바 컴파일러가finally 서브문장을 컴파일할 때 jsr명령을 생성합니다. 이것은 jvm를 마이크로 서브루틴으로 변환하여 실행합니다. 즉finally 블록에 있는 프로그램의 Return 0 문장을 jsr명령을 호출하기 전 창고에 있는 반환 변수를 국부 변수로 컴파일합니다. jsr명령을 호출하고finally 블록을 실행하고finally 블록을 반환합니다. 국부 변수에 있는 반환 값을 창고에 눌러서ireturn 명령을 실행하고 창고에서 반환 값을 출력합니다.호출 방법으로 되돌려줍니다. jsr 명령을 실행하기 전에 되돌려 주는 값을 국부 변수에 저장합니다. finally 블록이 실행하는 과정에서 이상이 발생하거나 되돌려 주는 값도 있기 때문입니다. 이렇게 해야만 마지막 프로그램이 실행하는 일치성을 확보할 수 있습니다.을 쓴 지 이미 몇 년이 되었기 때문에 작가가 사용한 jvm 컴파일러의 실현과 버전은 본고에서 논의한 것과 차이가 있다.따라서 테스트를 통해 같은 프로그램의 다른 컴파일러가 구현되거나 버전이 다른 바이트 코드의 생성에 약간의 차이가 있다.흥미가 있으면 이 책에서finally 자구가 생성한 바이트 코드를 볼 수 있다.
본고의 바이트 생성은 Oracle의 jdk8u-25 버전의 컴파일러를 사용하여 생성되었습니다.
다음은 실례를 하나 봅시다.
1.try catch finally 예:

public class FinallyTest {
  public static void main(String[] args) {

    int r = test();
    System.out.println(r);

  }
  public static int test()
  {
    try {
      System.out.println("try");
      //return 1/0;
      return 0;
    } catch (Exception e) {
      System.out.println("exception");
      return 100;
    }finally{
      System.out.println("finally");

    }

  }

}
try 블록에서 return 0 문구를 사용합니다. 프로그램의 실행 결과는 다음과 같습니다.
try
finally
0
try 블록에서 return 1/0 문구를 사용합니다. 프로그램이 실행된 결과는 다음과 같습니다.
exception
finally

사실 운행 결과를 통해 알 수 있듯이finally 블록은try나catch 블록의return 문장 앞의 다른 문장 뒤에 실행됩니다.즉, 프로그램의 쓰기 순서는 우리의 실행 순서와 일치하지 않는다. 왜냐하면 jvm는 바이트 코드를 해석하고 실행하기 때문이다. 그러면 우리는 자바 컴파일러가 이 코드를 어떻게 컴파일하는지 보고 생성된 바이트 코드가 도대체 어떤 것인지 봐야 한다.
2. 프로그램이 생성한 부분 바이트: (java 바이트 명령 참조)

public static int test();
  descriptor: ()I
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
   stack=2, locals=2, args_size=0
     0: getstatic   #20         // Field java/lang/System.out:Ljava/io/PrintStream;
     3: ldc      #36         // String try
     5: invokevirtual #38         // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     8: getstatic   #20         // Field java/lang/System.out:Ljava/io/PrintStream;
    11: ldc      #41        // String finally
    13: invokevirtual #38         // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    16: iconst_0
    17: ireturn
    18: astore_0
    19: getstatic   #20         // Field java/lang/System.out:Ljava/io/PrintStream;
    22: ldc      #43         // String exception
    24: invokevirtual #38         // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    27: getstatic   #20         // Field java/lang/System.out:Ljava/io/PrintStream;
    30: ldc      #41         // String finally
    32: invokevirtual #38         // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    35: bipush    100
    37: ireturn
    38: astore_1
    39: getstatic   #20         // Field java/lang/System.out:Ljava/io/PrintStream;
    42: ldc      #41         // String finally
    44: invokevirtual #38         // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    47: aload_1
    48: athrow
   Exception table:
     from  to target type
       0   8  18  Class java/lang/Exception
       0   8  38  any
      18  27  38  any
빨간색 부분에서 알 수 있듯이 10,11행은finally 블록 문장 지령이고 16,17은return 0 지령이며 try 블록의 다른 문장 다음에return 이전이다.19,20에 대응하는 것은finally 블록 명령이고 21,22에 대응하는 것은return 100문장의 명령이다.catch의 다른 문장에 대응하기 전에return 앞에서 우리는 이러한 배후에서 발생하는 모든 것이java컴파일러가 우리에게 이 모든 것을 해 주었음을 알 수 있다. 프로그램에서 발생하는 이상에 대해 jvm는 이상표에서 대응하는 이상 처리 주소 위치를 찾아 실행한다.
따라서finally 블록의 문장은java컴파일러가try 블록과catch 블록return 문장에 삽입되기 전, 다른 문장 뒤에 삽입된다는 결론을 얻을 수 있습니다.여기서도 jsr 호출된 하위 루틴을 생성하지 않았습니다.그래서 try 블록을 실행하든catch 블록을 실행하든지, 최종적으로 방법이 돌아오기 전에finally 블록을 실행합니다.
이상의 이javafinally 블록의 집행 시기에 대한 전면적인 분석은 바로 편집자가 여러분께 공유한 모든 내용입니다. 여러분께 참고가 되고 저희를 많이 사랑해 주시기 바랍니다.

좋은 웹페이지 즐겨찾기