linux下JNI開發步驟詳解


前期准備:

1、Java JDK

2、gcc

3、g++

注意:gcc和g++的版本號要一致:如下:

[juan@juan~]$ gcc --version  
gcc (GCC) <span style="color: #ff0000;" > 4.6 . 3   20120306  (Red Hat  4.6 . 3 - 2 )</span>  
Copyright (C) 2011  Free Software Foundation, Inc.  
This is free software; see the source for copying conditions.  There is NO  
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  
[qiaoning@qiaoning ~]$ g++ --version  
bash: g++: command not found...  
[qiaoning@qiaoning ~]$ gcc --version  
gcc (GCC) <span style="color: #ff0000;" > 4.6 . 3   20120306  (Red Hat  4.6 . 3 - 2 )</span>  
Copyright (C) 2011  Free Software Foundation, Inc.  
This is free software; see the source for copying conditions.  There is NO  
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

linux(Fedora) 安裝gcc yum install gcc 安裝g++ yum install gcc-c++

確保上述准備工作完成后開始下邊的工作:

Java代碼:

public   class  Hello {  
    static  {  
        try  {  
            System.loadLibrary("hello" );              
        } catch  (UnsatisfiedLinkError e) {  
            e.printStackTrace();  
        }  
    }  
      
    public  Hello() {};  
      
    public   native   void  SayHello(String strName);  
}  

在終端輸入 javac Hello.java 后生成Hello.class 文件

然后:javah Hello 生成 Hello.h文件

 

然后在相同的目錄下新建一個Hello.cpp文件:內容如下:

 

Cpp代碼
#include "Hello.h"   
#include <stdio.h>   
// 與 Hello.h 中函數聲明相同   
JNIEXPORT void  JNICALL Java_Hello_SayHello  (JNIEnv * env, jobject arg, jstring instring)  
{  
  // 從 instring 字符串取得指向字符串 UTF 編碼的指針   
  const  jbyte *str =  
    (const  jbyte *)env->GetStringUTFChars( instring, JNI_FALSE );  
  printf("Hello,%s\n" ,str);  
  // 通知虛擬機本地代碼不再需要通過 str 訪問 Java 字符串。   
  env->ReleaseStringUTFChars( instring, (const   char  *)str );  
  return ;  
}  

 

接下來編譯生成共享庫:
gcc -I/usr/lib/jvm/java- 1.6 . 0 -openjdk- 1.6 . 0.0 /include -I/usr/lib/jvm/java- 1.6 . 0 -openjdk- 1.6 . 0.0 /include/linux -fPIC -c Hello.cpp  

 

注意:這兒可能產生的錯誤:

gcc: error trying to exec  'cc1plus' : execvp: No such file or directory 

原因:沒有安裝g++,或者gcc和g++的版本不一致

 

 

/usr/lib/jvm/java- 1.6 . 0 -openjdk- 1.6 . 0.0  根據自己機器實際的目錄做相應的調整 

編譯成功后生成Hello.o

gcc -shared -Wl,-soname,libhello.so. 1  -o libhello.so. 1.0  Hello.o 
gcc -shared  
-Wl,-soname,libhello.so.1 -o libhello.so.1.0 Hello.o 

此命令生成生成 libhello.so.1.0

接下來將生成的共享庫拷貝為標准文件名

cp libhello.so. 1.0  libhello.so  

最后通知動態鏈接程序此共享文件的路徑。

export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH  

 

接下來將生成的共享庫拷貝為標准文件名

 

cp libhello.so.1.0 libhello.so

 

最后通知動態鏈接程序此共享文件的路徑。

 

export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH 

 

最后是java測試代碼:

 

public   class  ToSay   
 {   
     public   static   void  main(String argv[])   
     {   
         ToSay say = new  ToSay();   
     }   
     public  ToSay()   
     {   
         Hello h = new  Hello();   
         // 調用本地方法向 John 問好   
         h.SayHello("John" );              
     }   
 }   

 

用 javac 編譯 ToSay.java,生成 ToSay.class 
向執行普通 Java 程序一樣使用 java ToSay,我們會看到在屏幕上出現 Hello,John。 


 

應用中注意事項:

1 . 如果可以通過 TCP/IP 實現 Java 代碼與本地 C/C++ 代碼的交互工作,那么最好不使用以上提到的 JNI 的方式,因為一次 JNI 調用非常耗時,大概要花 0.5 ~ 1 個毫秒。

2 . 在一個 Applet 應用中,不要使用 JNI。因為在 applet 中可能引發安全異常。

3 . 將所有本地方法都封裝在單個類中,這個類調用單個 DLL。對於每種目標操作系統,都可以用特定於適當平台的版本替換這個 DLL。這樣就可以將本地代碼的影響減至最小,並有助於將以后所需的移植問題包含在內。

4 . 本地方法要簡單。盡量將生成的 DLL 對任何第三方運行時 DLL 的依賴減到最小。使本地方法盡量獨立,以將加載 DLL 和應用程序所需的開銷減到最小。如果必須要運行時 DLL,則應隨應用程序一起提供它們。

5 . 本地代碼運行時,沒有有效地防數組越界錯誤、錯誤指針引用帶來的間接錯誤等。所以必須保證保證本地代碼的穩定性,因為,絲毫的錯誤都可能導致 Java 虛擬機崩潰。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM