1. 程式人生 > >從本地方法棧看到jni呼叫

從本地方法棧看到jni呼叫

我們都知道java虛擬機器所管理的記憶體區域包括方法區,堆,虛擬機器棧,本地方法棧,程式計數器。 在《深入理解java虛擬機器》中,周志明老師對虛擬機器棧進行了講解,但是對本地方法棧卻一筆帶過。今天我們就來對本地方法棧做下深入...... 首先我們先回顧一下虛擬機器棧。 ###1.虛擬機器棧 ####1.1虛擬機器棧的特點 虛擬機器棧是執行緒私有的,它的生命週期與執行緒相同。 ####1.2虛擬機器棧的概念 虛擬機器棧是java方法執行的執行緒記憶體模型:每個java方法在執行時都會建立一個“棧幀”,棧幀的結構分為“區域性變量表,運算元棧,動態連結,方法出口”幾個部分。棧幀中的區域性變量表存放著一個方法的所有區域性變數。 對於java類中的方法來說:方法呼叫時,建立棧幀,並壓入虛擬機器棧;方法執行完畢,棧幀出棧並銷燬。 ####1.3關於虛擬機器棧的異常 單個執行緒請求的棧深度大於虛擬機器允許的深度,則會丟擲StackOverflowError; 當整個虛擬機器棧記憶體耗盡時,無法再申請到記憶體會丟擲OutOfMemoryError; ###2.本地方法棧 虛擬機器棧服務於java方法,本地方法棧服務於Native方法。 ####2.1那麼何為Native方法? 其實Native方法是一個用native關鍵字修飾的方法,它實質上就是一個java呼叫其它語言的介面(像呼叫C,C++等)。 看到這裡想到了什麼?JNI呼叫的時候就是依託於Native方法。 ####2.2為什麼會有native方法 ①儘管java很好用,但是效率上不如c和c++ ②java需要和底層作業系統或者和硬體互動 ###3.用native的方式實現jni (這並不是我們在Android開發中使用的方式,但是原理上是相同的) ####3.1 編寫我們的Native方法,建立MyNative.java檔案 ``` public class MyNative { public static native String myPrint(); static { System.loadLibrary("print"); } public static void main(String[] args){ new MyNative().myPrint(); } } ``` ####3.2 編譯.java檔案,生成位元組碼檔案 ####3.3 獲取.h檔案 通過javah -jni MyNative就會產生一個MyNative.h檔案。 ``` /* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class MyNative */ #ifndef _Included_MyNative #define _Included_MyNative #ifdef __cplusplus extern "C" { #endif /* * Class: MyNative * Method: myPrint * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_MyNative_myPrint (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif ``` ####3.4編寫print.cpp檔案 ``` #include 'MyNative.h' JNIEXPORT jstring JNICALL Java_MyNative_myPrint (JNIEnv *env, jclass jobj) { return env->NewStringUTF("hellonative"); } ``` 編譯後生成dll檔案 ####3.5 執行MyNative檔案,列印