? 對(duì)于一個(gè)運(yùn)行中的Java程序而言,它還可能會(huì)用到一些跟本地方法相關(guān)的數(shù)據(jù)區(qū)。當(dāng)某個(gè)線程調(diào)用一個(gè)本地方法時(shí),它就進(jìn)入了一個(gè)全新的并且不再受虛擬機(jī)限制的世界。本地方法可以通過(guò)本地方法接口來(lái)訪問(wèn)虛擬機(jī)的運(yùn)行時(shí)數(shù)據(jù)區(qū),但不止如此,它還可以做任何它想做的事情。
本地方法本質(zhì)上時(shí)依賴于實(shí)現(xiàn)的,虛擬機(jī)實(shí)現(xiàn)的設(shè)計(jì)者們可以自由地決定使用怎樣的機(jī)制來(lái)讓Java程序調(diào)用本地方法。
任何本地方法接口都會(huì)使用某種本地方法棧。當(dāng)線程調(diào)用Java方法時(shí),虛擬機(jī)會(huì)創(chuàng)建一個(gè)新的棧幀并壓入Java棧。然而當(dāng)它調(diào)用的是本地方法時(shí),虛擬機(jī)會(huì)保持Java棧不變,不再在線程的Java棧中壓入新的幀,虛擬機(jī)只是簡(jiǎn)單地動(dòng)態(tài)連接并直接調(diào)用指定的本地方法。
如果某個(gè)虛擬機(jī)實(shí)現(xiàn)的本地方法接口是使用C連接模型的話,那么它的本地方法棧就是C棧。當(dāng)C程序調(diào)用一個(gè)C函數(shù)時(shí),其棧操作都是確定的。傳遞給該函數(shù)的參數(shù)以某個(gè)確定的順序壓入棧,它的返回值也以確定的方式傳回調(diào)用者。同樣,這就是虛擬機(jī)實(shí)現(xiàn)中本地方法棧的行為。
很可能本地方法接口需要回調(diào)Java虛擬機(jī)中的Java方法,在這種情況下,該線程會(huì)保存本地方法棧的狀態(tài)并進(jìn)入到另一個(gè)Java棧。
下圖描繪了這樣一個(gè)情景,就是當(dāng)一個(gè)線程調(diào)用一個(gè)本地方法時(shí),本地方法又回調(diào)虛擬機(jī)中的另一個(gè)Java方法。
這幅圖展示了JAVA虛擬機(jī)內(nèi)部線程運(yùn)行的全景圖。一個(gè)線程可能在整個(gè)生命周期中都執(zhí)行Java方法,操作它的Java棧;或者它可能毫無(wú)障礙地在Java棧和本地方法棧之間跳轉(zhuǎn)。

該線程首先調(diào)用了兩個(gè)Java方法,而第二個(gè)Java方法又調(diào)用了一個(gè)本地方法,這樣導(dǎo)致虛擬機(jī)使用了一個(gè)本地方法棧。假設(shè)這是一個(gè)C語(yǔ)言棧,其間有兩個(gè)C函數(shù),第一個(gè)C函數(shù)被第二個(gè)Java方法當(dāng)做本地方法調(diào)用,而這個(gè)C函數(shù)又調(diào)用了第二個(gè)C函數(shù)。之后第二個(gè)C函數(shù)又通過(guò)本地方法接口回調(diào)了一個(gè)Java方法(第三個(gè)Java方法),最終這個(gè)Java方法又調(diào)用了一個(gè)Java方法(它成為圖中的當(dāng)前方法)。