摘要:則會(huì)在轉(zhuǎn)移指令前執(zhí)行。總結(jié)與之間的關(guān)系如果在中含有語句,那么語句的還有作用嗎先看一段代碼如果你對內(nèi)存布局不是很清楚,請看這篇文章虛擬機(jī)類加載機(jī)制和字節(jié)碼執(zhí)行引擎重點(diǎn)關(guān)注運(yùn)行時(shí)棧幀結(jié)構(gòu)局部變量表槽,操作數(shù)棧。
定論
問:finally語句一定會(huì)執(zhí)行嗎?
答:
如果沒有執(zhí)行相應(yīng)的try語句則不會(huì)執(zhí)行。
在try語句中如果調(diào)用System.exit(0)方法則不會(huì)執(zhí)行。
問:finally會(huì)在什么時(shí)候執(zhí)行?
答:如果在try/catch語句中調(diào)用轉(zhuǎn)移指令例如:return,break,continue,throw等。則會(huì)在轉(zhuǎn)移指令前執(zhí)行。
如果在finally中含有return語句,那么try/catch語句的return還有作用嗎?
先看一段代碼:
/** * Created by gavin on 15-9-2. */ public class FinallyTest { public static void main(String[] args){ System.out.println(test1()); //3 System.out.println(test2()); //3 System.out.println(test3()); //2 System.out.println(test4()); //2 } public static int test1() { int i = 1; try { i = 2; return i; }finally { i++; return i; } } public static int test2() { int i = 1; try { i = 2; return i; }finally { i = 3; return i; } } public static int test3() { int i = 1; try { i = 2; return i; }finally { i++; } } public static int test4() { int i = 1; try { i = 2; return i; }finally { i = 3; } } }
如果你對java內(nèi)存布局不是很清楚,請看這篇文章:java虛擬機(jī)類加載機(jī)制和字節(jié)碼執(zhí)行引擎
重點(diǎn)關(guān)注運(yùn)行時(shí)棧幀結(jié)構(gòu)(局部變量表槽,操作數(shù)棧)。
上邊的代碼非常簡單,來看一下字節(jié)碼指令吧
public static int test1(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=0 0: iconst_1 //定義一個(gè)常量1入棧到操作數(shù)棧 //棧1 0: 1: 1: istore_0 //出棧,存儲(chǔ)到局部便量表槽0 //棧 0:1 1: 2: iconst_2 //定義一個(gè)常量2入棧到操作數(shù)棧 //棧2 0:1 1: 3: istore_0 //出棧,存儲(chǔ)到局部變量表槽0 //棧 0:2 1: 4: iload_0 //從局部便量表槽0入棧到操作數(shù)棧 //棧2 0:2 1: 5: istore_1 //出棧,存儲(chǔ)到局部變量表槽1 //棧 0:2 1:2 6: iinc 0, 1 //局部變量表槽0變量加1 //棧 0:3 1:2 9: iload_0 //從局部變量表槽0入棧到操作數(shù)棧 //棧3 0:3 1:2 10: ireturn //結(jié)束,返回 //棧3 0:3 1:2 11: astore_2 12: iinc 0, 1 15: iload_0 16: ireturn public static int test2(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=0 0: iconst_1 //定義一個(gè)常量1入棧到操作數(shù)棧 //棧1 0: 1: 1: istore_0 //出棧,存儲(chǔ)到局部便量表槽0 //棧 0:1 1: 2: iconst_2 //定義一個(gè)常量2入棧到操作數(shù)棧 //棧2 0:1 1: 3: istore_0 //出棧,存儲(chǔ)到局部變量表槽0 //棧 0:2 1: 4: iload_0 //從局部變量表槽0入棧 //棧2 0:2 1: 5: istore_1 //出棧,存儲(chǔ)到局部變量表槽1 //棧 0:2 1:2 6: iconst_3 //定義一個(gè)常量3入棧 //棧3 0:2 1:2 7: istore_0 //出棧,存儲(chǔ)到局部便量表槽0 //棧 0:3 1:2 8: iload_0 //從局部變量表槽0入棧 //棧3 0:3 1:2 9: ireturn //結(jié)束,返回 //棧3 0:3 1:2 10: astore_2 11: iconst_3 12: istore_0 13: iload_0 14: ireturn public static int test3(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=0 0: iconst_1 //定義一個(gè)常量1入棧到操作數(shù)棧 //棧1 0: 1: 1: istore_0 //出棧,存儲(chǔ)到局部便量表槽0 //棧 0:1 1: 2: iconst_2 //定義一個(gè)常量2入棧到操作數(shù)棧 //棧2 0:1 1: 3: istore_0 //出棧,存儲(chǔ)到局部變量表槽0 //棧 0:2 1: 4: iload_0 //從局部變量表槽0入棧 //棧2 0:2 1: 5: istore_1 //出棧,存儲(chǔ)到局部變量表槽1 //棧 0:2 1:2 6: iinc 0, 1 //局部變量表槽0變量加一 //棧 0:3 1:2 9: iload_1 //從局部變量表槽1入棧 //棧2 0:3 1:2 10: ireturn //結(jié)束,返回 //棧2 0:3 1:2 11: astore_2 12: iinc 0, 1 15: aload_2 16: athrow public static int test4(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=0 0: iconst_1 //定義一個(gè)常量1入棧到操作數(shù)棧 //棧1 0: 1: 1: istore_0 //出棧,存儲(chǔ)到局部便量表槽0 //棧 0:1 1: 2: iconst_2 //定義一個(gè)常量2入棧到操作數(shù)棧 //棧2 0:1 1: 3: istore_0 //出棧,存儲(chǔ)到局部變量表槽0 //棧 0:2 1: 4: iload_0 //從局部變量表槽0入棧 //棧2 0:2 1: 5: istore_1 //出棧,存儲(chǔ)到局部變量表槽1 //棧 0:2 1:2 6: iconst_3 //定義一個(gè)常量3入棧到操作數(shù)棧 //棧3 0:2 1:2 7: istore_0 //出棧,存儲(chǔ)到局部變量表槽0 //棧 0:3 1:2 8: iload_1 //從局部變量表槽1入棧 //棧2 0:3 1:2 9: ireturn //結(jié)束,返回 //棧2 0:3 1:2 10: astore_2 11: iconst_3 12: istore_0 13: aload_2 14: athrow
我們看到:
在finally中沒有return時(shí),棧中最后存儲(chǔ)的數(shù)據(jù)是try/catch中操作后數(shù)據(jù)。即finally操作后的數(shù)據(jù)存儲(chǔ)到其他槽中,而后再加載try/catch操作后的數(shù)據(jù)。
而在finally中含有return時(shí),棧中最后存儲(chǔ)的數(shù)據(jù)是finally中操作后的數(shù)據(jù)。即finally操作后的數(shù)據(jù)存儲(chǔ)到其他槽中,而后加載的是其他槽(finally)中的數(shù)據(jù)。
也就是說:如果finally中不含有return語句,finally對try/catch操作的八大基礎(chǔ)類型不會(huì)再加載到操作數(shù)棧中。
如果返回值是對象引用,finally中的return還有待考據(jù)。
參考:關(guān)于 Java 中 finally 語句塊的深度辨析
更多文章:http://blog.gavinzh.com
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/64459.html
摘要:順序一致性內(nèi)存模型有兩大特性一個(gè)線程中所有操作必須按照程序的順序執(zhí)行。這里的同步包括對常用同步原語的正確使用通過以下程序說明與順序一致性兩種內(nèi)存模型的對比順序一致性模型中所有操作完全按程序的順序串行執(zhí)行。 java內(nèi)存模型 java內(nèi)存模型基礎(chǔ) happen-before模型 JSR-133使用happen-before的概念來闡述操作之間的內(nèi)存可見性。在JMM中,如果一個(gè)操作執(zhí)行的結(jié)...
摘要:對于域,編譯器和處理器要遵守兩個(gè)重排序規(guī)則在構(gòu)造函數(shù)內(nèi)對一個(gè)域的寫入,與隨后把這個(gè)被構(gòu)造對象的引用賦值給一個(gè)引用變量,這兩個(gè)操作之間不能重排序。這個(gè)屏障禁止處理器把域的寫重排序到構(gòu)造函數(shù)之外。下一篇深入理解內(nèi)存模型七總結(jié) 與前面介紹的鎖和volatile相比較,對final域的讀和寫更像是普通的變量訪問。對于final域,編譯器和處理器要遵守兩個(gè)重排序規(guī)則: 在構(gòu)造函數(shù)內(nèi)對一個(gè)fi...
摘要:本篇文章主要是跟大家聊聊的內(nèi)部架構(gòu)體系,讓大家對有個(gè)整體的認(rèn)知。方法會(huì)創(chuàng)建一個(gè)對象,調(diào)用它的方法將字節(jié)流封裝成對象,在創(chuàng)建組件時(shí),會(huì)將組件添加到組件中組件而組件在連接器初始化時(shí)就已經(jīng)創(chuàng)建好了目前為止,只有一個(gè)實(shí)現(xiàn)類,就是。 微信公眾號(hào)「后端進(jìn)階」,專注后端技術(shù)分享:Java、Golang、WEB框架、分布式中間件、服務(wù)治理等等。 老司機(jī)傾囊相授,帶你一路進(jìn)階,來不及解釋了快上車! T...
摘要:前提深入理解內(nèi)存模型程曉明著,該書在以前看過一遍,現(xiàn)在學(xué)的東西越多,感覺那塊越重要,于是又再細(xì)看一遍,于是便有了下面的讀書筆記總結(jié)。同步同步是指程序用于控制不同線程之間操作發(fā)生相對順序的機(jī)制。線程之間的通信由內(nèi)存模型控制。 showImg(https://mmbiz.qpic.cn/mmbiz_jpg/1flHOHZw6RtPu3BNx3zps1JhSmPICRw7QgeOmxOfTb...
閱讀 1464·2023-04-25 17:18
閱讀 1894·2021-10-27 14:18
閱讀 2135·2021-09-09 09:33
閱讀 1852·2019-08-30 15:55
閱讀 2025·2019-08-30 15:53
閱讀 3449·2019-08-29 16:17
閱讀 3436·2019-08-26 13:57
閱讀 1739·2019-08-26 13:46