2011-08-28 122 views
9

我只是很好奇Java JVM有可能有時內聯有可能拋出異常的方法。我認爲有可能內聯至少一些這樣的方法(例如那些有陣列訪問並因此可能拋出ArrayIndexOutOfBoundsException)的方法。我看到的問題是,如果實際發生異常,如果您已經內聯該方法,如何顯示正確的堆棧跟蹤?由於可以在不同的機器上內聯不同的方法,因此內聯如何不破壞堆棧跟蹤機制?如何插入方法拋出異常?

+2

在C++中,內聯幾乎可以保證堆棧信息的丟失。但是,一個異常堆棧跟蹤丟失一幀的事實並不是世界的盡頭;它只是內聯的公認結果(並且編譯器提供調試模式選項來抑制所有內聯的原因之一)。我不知道Java的行爲是否相同。 –

+0

我的意思是這是一個Java問題,但有趣的是要知道它是如何在C++中工作的。 – Gravity

回答

8

您設想的問題是什麼?因爲JVM本身是內聯的,所以沒有什麼能夠阻止它記住內聯的內容,並在構建堆棧跟蹤以便安裝到Throwable對象時修正此問題。

當引發例外構造時,JVM將遍歷CPU堆棧並確定每個機器堆棧幀是否對應於解釋的字節碼,JITted代碼,庫中的本地代碼等等。爲此,它指的是表格,它告訴機器代碼中的哪些地址對應於來自字節碼的哪些指令(並且如果該信息存在於類文件中,則返回源代碼行)。該表格可以很好地指定JITted代碼中的某個位置可以對應多個Java級別的堆棧幀。

但是,JVM不是需要來做到這一點。它也可以選擇簡單地構建帶有神祕中斷的堆棧軌跡。請參閱javadoc for Throwable.getStackTrace()。 (甚至沒有要求JVM能夠產生堆棧跟蹤在所有)。

3

你可能想看看this document這也解釋了異常處理在JVM是如何工作的:

是 捕獲異常與一個異常表是 在類文件與交付一起相關聯的每個方法字節碼序列的 方法。異常表有一個條目,每個例外都有 被每個try塊捕獲。每個條目有四條信息: 開始和結束點,字節碼序列 內的pc偏移量跳轉到,並捕獲異常類的常量池索引 被捕獲。

+0

我有興趣查看。不過,我具體詢問內聯與異常的相互作用。看起來,如果函數內聯,堆棧跟蹤信息應該丟失,但它似乎並不在Java程序中。 – Gravity

+1

請記住,Java中的內聯發生在運行時,而不是像C/C++那樣的編譯時間,所以你不會「丟失」任何信息。任何經過優化並需要檢索的信息都可以存儲在查找/跳轉表中。 –

+0

不會在查找表中存儲異常信息會導致不可接受的性能,尤其是對於非常常見的異常(如ArrayIndexOutOfBounds)? – Gravity