Linux平台下使用JNI

來源:互聯網
上載者:User

1 首先建立一個簡單的java類:

public class Hello
{
 static
 {
  try
  {
//此處即為本地方法所在連結庫名
   System.loadLibrary("hello");
  }
  catch(UnsatisfiedLinkError e)
  {
   System.err.println( "Cannot load hello library:\n " +
                                e.toString() );
  }
 }
 public Hello()
 {
 }
//聲明的本地方法
  public native void SayHello(String strName);
}

這裡有個地方要注意,就是 這個類最好不要加包資訊。因為類在某個包下面,使用javah命令產生*.h標頭檔的時候會不一樣,比如在test包下,就會產生test_Hello.h,而且 在jni調用的時候,也有區別,為了方便起見,我們這裡就不加包了,免得麻煩,:)

然後,編譯得到Hello.class

2 產生 Hello.h

  使用命令:javah Hello

  這裡有一點要注意,如果這個命令報錯,有可能是因為你沒有當前路徑到設定環境變數classpath中,所以:

  javah -classpath"." Hello.class

  這樣寫就OK了, 後面也許還會碰到類似的環境變數問題。

3 在與Hello.h相同的路徑下建立一個CPP檔案Hello.cpp。內容如下:

#include "Hello.h"JNIEXPORT void JNICALL Java_Hello_SayHello  (JNIEnv * env, jobject arg, jstring instring){    const char *str = env->GetStringUTFChars( instring, JNI_FALSE );    printf("Hello,%s\n",str);    env->ReleaseStringUTFChars( instring, str );    return;}
這個Hello.cpp 的代碼,跟IBM的例子略有不同,詳細原因 大家自己去查查jni.h
4.編譯產生共用庫
a. 編譯命令,產生Hello.o
g++ -I /usr/lib/jvm/java-6-sun-1.6.0.03/include -I /usr/lib/jvm/java-6-sun-1.6.0.03/include/linux -fPIC -c Hello.cpp
b.產生動態庫檔案,libhello.so.1.0
g++ -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 Hello.o
這裡的2個命令也跟IBM文章的例子有所不同。因為使用gcc編譯得到動態庫,在jni調用的時候,某些情況會有異常,所以這裡改用g++。

接下來將產生的共用庫拷貝為標準檔案名稱

cp libhello.so.1.0 libhello.so

最後通知動態連結程式此共用檔案的路徑。

export LD_LIBRARY_PATH='pwd':$LD_LIBRARY_PATH

 

這裡用export 加入共用檔案的路徑,有時候會有點問題,比如:環境變數不會馬上更新等等。

還有一個辦法,就是直接將libhello.so拷貝到 /usr/lib 或者/lib 等系統庫目錄下

 

 

5.編寫一個簡單的Java程式來測試我們的本地方法。

將如下源碼存為ToSay.java:

import Hello;import java.util.*;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。
 
6 以下是IBM的文章中的建議:

應用中注意事項

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虛擬機器崩潰。

 

 

7 思考的問題

我以前一直在想,如果我使用JNI來調用C/C++實現的socket通訊庫,會不會比java自己的nio效能要好?

貌似IBM的兄弟的回答是否定的。

 

也有人不同意這個意見,說因為Java代碼與本地C/C++代碼的互動工作不是那麼頻繁,即使浪費0.5~1個毫秒,也沒什麼關係。

貌似BEA的weblogic(weblogic 9以後的版本)就採用這個做法。

 

以後有機會我就來做個實驗,測試一下,呵呵。

當然,有兄弟已經測試過了,來告訴我,就最好啦,哈哈!!!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.