欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java finally塊執(zhí)行時(shí)機(jī)全面分析

 更新時(shí)間:2016年08月18日 10:15:41   投稿:jingxian  
下面小編就為大家?guī)?lái)一篇java finally塊執(zhí)行時(shí)機(jī)全面分析。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

java里 finally 關(guān)鍵字通常與try catch塊一起使用。用來(lái)在方法結(jié)束前或發(fā)生異常時(shí)做一些資源釋放的操作。最近也看到網(wǎng)上有一些討論try catch finally關(guān)鍵詞執(zhí)行的順序的文章,并給出了finally塊是在方法最后執(zhí)行的。

這些觀點(diǎn)普遍認(rèn)為:

1) finally關(guān)鍵詞是在程序return語(yǔ)句后返回上一級(jí)方法前執(zhí)行的,其中返回值會(huì)保存在一個(gè)臨時(shí)區(qū)域,待執(zhí)行完finally塊的部分后,在將臨時(shí)區(qū)域的值返回。

2) 若finally塊里有返回值會(huì)替換掉程序中前面的try 或catch塊中return語(yǔ)句存放在臨時(shí)區(qū)域的值。

但是問(wèn)題真的是這樣的嗎,我們仔細(xì)的想想,jvm是在運(yùn)行時(shí)對(duì)字節(jié)碼指令進(jìn)行解釋執(zhí)行的,當(dāng)他在執(zhí)行到return語(yǔ)句后,他哪知道后面有沒(méi)有finally塊,如果沒(méi)有finally塊怎么辦,不管是字節(jié)碼指令還是計(jì)算機(jī)的指令應(yīng)該是明確的,jvm沒(méi)有那么智能,同一個(gè)指令必須是明確的,不會(huì)包含兩層含義。所以對(duì)于return語(yǔ)句在運(yùn)行時(shí)不管什么情況,統(tǒng)一會(huì)彈出棧的內(nèi)容并返回到調(diào)用方法。

與此同時(shí),我們可以看到《深入java虛擬機(jī)》這一本書(shū)中給出了另外一種解釋。在java編譯器編譯finally子句時(shí)會(huì)生成jsr指令,它使jvm調(diào)轉(zhuǎn)到微型子例程進(jìn)行執(zhí)行,也就是finally塊處,同時(shí)將程序中的return 0語(yǔ)句編譯為在調(diào)用jsr指令前棧中的返回變量到局部變量,調(diào)用jsr指令,執(zhí)行finally塊,finally塊返回,在將局部變量中的返回值壓入棧,執(zhí)行ireturn指令,從棧中彈出返回值,返回到調(diào)用方法,這里在執(zhí)行jsr指令前將返回值保存在局部變量中,是因?yàn)閒inally塊執(zhí)行的過(guò)程中可能發(fā)生異?;蛘哒f(shuō)是也有返回值,只有這樣做才能保證最后程序執(zhí)行的一致性。由于《深入java虛擬機(jī)》寫(xiě)的已經(jīng)也一些年代了,同時(shí)作者使用的jvm編譯器的實(shí)現(xiàn)及版本與本文討論的也有差別。所以經(jīng)過(guò)測(cè)試,對(duì)于同一程序不同的編譯器實(shí)現(xiàn)或版本不同的字節(jié)碼的生成稍微有些差別。有興趣可以看看這本書(shū)中finally子句生成的字節(jié)碼。

本文的字節(jié)碼生成使用的是Oracle的jdk8u-25版本的編譯器編譯生成的。

下面我們來(lái)看一個(gè)實(shí)例。

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語(yǔ)句,程序的運(yùn)行結(jié)果是:

try
finally
0

try塊中使用 return 1/0 語(yǔ)句,程序運(yùn)行的結(jié)果是:

exception
finally
100

其實(shí)通過(guò)運(yùn)行結(jié)果我們可以看出的是finally塊是在try或catch塊中的return語(yǔ)句前其他語(yǔ)句后執(zhí)行的。也就是說(shuō)程序的書(shū)寫(xiě)順序與我們執(zhí)行順序不符,因?yàn)閖vm是對(duì)字節(jié)碼進(jìn)行解釋執(zhí)行的,那么我們需要看看java編譯器是如何編譯這段代碼的,看看其生成的字節(jié)碼究竟是什么樣的。

2.程序生成的部分字節(jié)碼:(java字節(jié)碼指令請(qǐng)參考)

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行對(duì)應(yīng)的是finally塊語(yǔ)句指令,16,17對(duì)應(yīng)的是return 0指令,在try塊其他語(yǔ)句之后,return之前。而19,20對(duì)應(yīng)的是finally塊指令,21,22對(duì)應(yīng)的是return 100語(yǔ)句的指令,在catch其他語(yǔ)句之后,return之前,由此我們可以看出這些背后發(fā)生的一切是java編譯器為我們做了這一切,至于程序中發(fā)生的異常,jvm會(huì)從異常表找到對(duì)應(yīng)處理異常的地址位置執(zhí)行。

因此我們可以得出結(jié)論finally塊中的語(yǔ)句會(huì)由java編譯器插入到try塊和catch塊return語(yǔ)句之前,其他語(yǔ)句之后。在這里也沒(méi)有生成jsr調(diào)用的子例程。所以才發(fā)生不管是執(zhí)行try塊還是執(zhí)行catch塊,最終在方法返回前都會(huì)執(zhí)行finally塊。

以上這篇java finally塊執(zhí)行時(shí)機(jī)全面分析就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java實(shí)現(xiàn)的連續(xù)奇數(shù)(n+2*x)是合數(shù)的算法題暴力算法

    Java實(shí)現(xiàn)的連續(xù)奇數(shù)(n+2*x)是合數(shù)的算法題暴力算法

    這篇文章主要介紹了Java實(shí)現(xiàn)的連續(xù)奇數(shù)(n+2*x)是合數(shù)的算法題暴力算法,本文包含運(yùn)算結(jié)果和實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2014-09-09
  • Java設(shè)計(jì)模式之外觀模式示例詳解

    Java設(shè)計(jì)模式之外觀模式示例詳解

    外觀模式為多個(gè)復(fù)雜的子系統(tǒng),提供了一個(gè)一致的界面,使得調(diào)用端只和這個(gè)接口發(fā)生調(diào)用,而無(wú)須關(guān)系這個(gè)子系統(tǒng)內(nèi)部的細(xì)節(jié)。本文將通過(guò)示例詳細(xì)為大家講解一下外觀模式,需要的可以參考一下
    2022-03-03
  • SpringBoot復(fù)雜參數(shù)應(yīng)用詳細(xì)講解

    SpringBoot復(fù)雜參數(shù)應(yīng)用詳細(xì)講解

    我們?cè)诰帉?xiě)接口時(shí)會(huì)傳入復(fù)雜參數(shù),如Map、Model等,這種類似的參數(shù)會(huì)有相應(yīng)的參數(shù)解析器進(jìn)行解析,并且最后會(huì)將解析出的值放到request域中,下面我們一起來(lái)探析一下其中的原理
    2022-09-09
  • 詳解Java編程的Observer觀察者設(shè)計(jì)模式

    詳解Java編程的Observer觀察者設(shè)計(jì)模式

    這篇文章主要介紹了Java編程的Observer觀察者設(shè)計(jì)模式,觀察者模式定義了一個(gè)一對(duì)多的依賴關(guān)系,讓一個(gè)或多個(gè)觀察者對(duì)象監(jiān)察一個(gè)主題對(duì)象,需要的朋友可以參考下
    2016-01-01
  • 淺談Java中注解Annotation的定義、使用、解析

    淺談Java中注解Annotation的定義、使用、解析

    下面小編就為大家?guī)?lái)一篇淺談Java中注解Annotation的定義、使用、解析。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • Java集合排序規(guī)則接口Comparator用法解析

    Java集合排序規(guī)則接口Comparator用法解析

    這篇文章主要介紹了Java集合排序規(guī)則接口Comparator用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • java內(nèi)存模型jvm虛擬機(jī)簡(jiǎn)要分析

    java內(nèi)存模型jvm虛擬機(jī)簡(jiǎn)要分析

    Java 內(nèi)存模型的主要目的是定義程序中各種變量的訪問(wèn)規(guī)則, 關(guān)注在虛擬機(jī)中把變量值存儲(chǔ)到內(nèi)存和從內(nèi)存中取出變量值這樣的底層細(xì)節(jié)
    2021-09-09
  • SpringCloud中的Seata基本介紹與安裝教程

    SpringCloud中的Seata基本介紹與安裝教程

    Seata 是一款開(kāi)源的分布式事務(wù)解決方案,致力于提供高性能和簡(jiǎn)單易用的分布式事務(wù)服務(wù),這篇文章主要介紹了SpringCloud之Seata基本介紹與安裝,需要的朋友可以參考下
    2024-01-01
  • Java字母大小寫(xiě)轉(zhuǎn)換的方法

    Java字母大小寫(xiě)轉(zhuǎn)換的方法

    這篇文章主要為大家詳細(xì)介紹了Java字母大小寫(xiě)轉(zhuǎn)換的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Java 網(wǎng)絡(luò)爬蟲(chóng)新手入門詳解

    Java 網(wǎng)絡(luò)爬蟲(chóng)新手入門詳解

    這篇文章主要介紹了Java 網(wǎng)絡(luò)爬蟲(chóng)新手入門詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10

最新評(píng)論