java jni 原理_JNI的实现原理
JNI接口函數(shù)和指針
Java虛擬機訪問本機代碼通過調(diào)用JNI的功能特性。JNI的功能都可以通過一個接口指針。一個接口指針是一個指向指針的指針。這個指針指向一個一個指針數(shù)組,這個數(shù)組中的每一個成員指向一個函數(shù)入口。每個接口的功能是在一個預定義的內(nèi)部數(shù)組的偏移量。
圖一、JNI接口函數(shù)和指針
JNI接口的組織像C++虛函數(shù)列表或COM接口一樣。使用接口列表的好處是JNI名字空間與本地代碼分離開來。
JNI接口指針只在當前線程有效。因此,一個本地方法不能從一個線程通過該接口指針指向另一個線程。
本地方法像參數(shù)一樣接收JNI接口指針。當在同一個線程中有多個調(diào)用本地方法,VM保證相同的接口指針傳遞到這個本地方法。然而,本地方法可以被不同的Java線程調(diào)用,因此可能會收到不同的JNI接口指針。
加載和鏈接本機方法
本地方法裝載的是System.loadLibrary方法。在下面的例子中,類的初始化方法加載一個特定平臺的本地庫中的本地方法f定義如下:
package
pkg;
class
Cls {
native
double f(int i, String s);
static
{
System.loadLibrary(“pkg_Cls”);
}
}
System.loadLibrary中的參數(shù)是一個庫名,它是由程序員任意選擇的。該系統(tǒng)遵循一個標準:把庫名轉(zhuǎn)換為本地庫名的方法,但這是與平臺相關(guān)的。例如,Solaris系統(tǒng)把pkg_Cls轉(zhuǎn)換為libpkg_Cls.so,而Win32系統(tǒng)則轉(zhuǎn)換為pkg_Cls.dll。
程序員可以使用一個單一的庫來存儲所有的任何類需要的本地方法,只要這些類能夠被同一類加載器加載。虛擬機內(nèi)部會為每個類加載器維護一個加載本地庫的的列表。
虛擬機會檢查與本地庫匹配的方法名。虛擬機會首先查找短名稱,即沒有參數(shù)的名稱簽名。然后,再查找長名稱,即帶參數(shù)簽名的名稱。程序員只有當一個本地方法與另一本機方法重載時才需要使用長名稱。
在下面的例子中,本地方法g不必須連接使用長名稱,因為其另一個方法g不是一個本地方法,因此也沒有在本地庫。
class
Cls1 {
int
g(int i);
native
int g(double d);
}
本機方法的參數(shù)
JNI接口指針是本地方法的第一個參數(shù)。在JNI接口指針的類型是JNIEnv。第二個參數(shù)不同,這取決于本地方法是靜態(tài)的還是非靜態(tài)的。第二個參數(shù)為一個非靜態(tài)本地方法時是對對象的引用。第二個參數(shù)為靜態(tài)本地方法是對的Java類的引用。
其余的參數(shù)對應于常規(guī)的Java方法的參數(shù)。本機方法通過返回值調(diào)用傳遞它的結(jié)果返回到調(diào)用例程。
下面代碼舉例說明了使用C函數(shù)來實現(xiàn)f本地方法時,本地方法f聲明如下:
package
pkg;
class
Cls {
native
double f(int i, String s);
...
}
Java對象引用
像整數(shù),字符,等等這些原始類型,都在Java與本機代碼之間復制。另外,任意Java對象,是通過引用傳遞。虛擬機必須跟蹤所有已傳遞到本地代碼的對象,使這些對象不會被垃圾收集器釋放。相反,本地代碼必須有一種機制來通知虛擬機什么時候不再需要使用這些對象了。此外,垃圾收集器必須能夠搬運對象所指的本機代碼。
全局和局部引用
JNI把本地代碼使用的相關(guān)對象分為兩在范疇:局部和全局引用。局部引用的有效期為一個本地方法調(diào)用的時間,并自動機方法返回后獲釋。全球引用仍然有效,直到它們被明確釋放。
所有的Java的JNI函數(shù)返回的對象都是局部引用。JNI允許程序員通過局部引用來創(chuàng)建全局引用。
局部引用只有在線程中被建立時才有效,并只在該線程中有效。本地代碼不能在線程之間調(diào)用局部引用。
訪問字段和方法
JNI允許本地代碼訪問字段和調(diào)用Java對象的方法。JNI通過符號名稱和類型簽名來判定方法和字段。例如,要調(diào)用類cls中的方法f,本地代碼首先獲得一個方法的ID,如下:
jmethodID
mid = env->GetMethodID(cls, “f”, “(ILjava/lang/String;)D”);
本地代碼便可以重復的使用method
ID而在方法查找時不需要時間,具體如下:
jdouble
result = env->CallDoubleMethod(obj, mid, 10, str);
報告程序錯誤
JNI不檢查編程錯誤,如空指針或非法參數(shù)類型傳遞。非法使用的參數(shù)類型包括用父類對象引用子類對象。
Java異常
JNI允許本地方法任意提高Java異常。本機代碼也可以處理嚴重的Java異常。Java的未處理的異常是傳送回了VM。
因此,程序員可以快速檢查上次的JNI調(diào)用的返回值,以確定是否發(fā)生了錯誤,并調(diào)用一個函數(shù),ExceptionOccurred(),以獲得異常對象,它包含一個錯誤的條件更詳細的說明。
異常處理
在本地代碼中有兩種方法處理異常:
1、本機方法可以選擇立即返回,在Java代碼中拋出異常,啟動了本地方法調(diào)用。
2、本地代碼能過調(diào)用ExceptionClear()來清除異常,然后執(zhí)行自己的異常處理代碼。
在異常被提升之后,本地代碼在其它JNI調(diào)用之前必須先清除異常。
總結(jié)
以上是生活随笔為你收集整理的java jni 原理_JNI的实现原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql数据库 日志类型_MySQL中
- 下一篇: 模板会有多层镜像_创建镜像的方法有三种: