經典面試題,try-catch-finally在虛擬機器中的實現
相信大家在面試中,或者其他情況下經常會看到這樣的一道題,下面inc()方法呼叫後的返回值是什麼,答案大家自己去執行下程式或者問度娘之後應該都知道了,在方法沒有異常的時候,返回的是1,出現Exception異常的時候返回的是2,出現Exception以外的異常致使方法非正常退出時,沒有返回值。但這樣的結果在虛擬機器的實現原理是什麼呢,我想很多童鞋是不知道的。
public int inc() { int x; try{ x = 1; return x; } catch(Exception e) { x = 2; return x; }finally { x = 3; } }
圖1-1
如圖1-1,是我用javap -verbose執行該方法後得到的該方法對應的Class檔案的位元組碼
從Exception table可以看到在正常執行時,是從第1步開始到第7步返回,首先將1賦值第二個本地變數(第1步-第2步),這裡的第二個本地變數就對應著x,再將x複製一份存入第三個本地變數(第3步-第4步)。接著執行finally中的賦值,將3賦值給x存入第二個本地變數,讀取第三個本地變數到操作棧頂,即1,並呼叫ireturn指令以int形式返回(第5步-第7步)。
如果報Exception,第4步執行之後將執行第8步,將2賦值給x存入第二個本地變數,複製2到第四個本地變數,接著執行finally中的賦值,將3賦值給x存入第二個本地變數,讀取第四個本地變數到操作棧頂,即2,並呼叫ireturn指令以int形式返回(第8步-第16步)。
如果出現其他狀況,將直接跳轉到第17步,將3賦值給x存入第二個本地變數。將異常推送至棧頂並丟擲。沒有呼叫ireturn,沒有返回值。
因此,才得到上面的結論,現在童鞋們都知道 了吧= =
虛擬機器位元組碼指令說明:
iconst_{i} : 將int型i推送至棧頂
istore_{i} : 將int型值存入第i+1個本地變數
iload_{i} : 將第i+1個int型本地變數推送至棧頂
ireturn : 從當前方法返回int
astore : 將棧頂引用型數值存入指定本地變數
aload : 將指定的引用型別本地變數推送至棧頂
athrow : 將棧頂的異常丟擲