Linux上從Java程序中調用C函數


  原則上來說,“100%純Java”的解決方法是最好的,但有些情況下必須使用本地方法。特別是在以下三種情況:

  • 需要訪問Java平台無法訪問的系統特性和設備;
  • 通過基准測試,發現Java代碼比其他語言編寫的等價代碼慢得多;
  • 其他語言編寫的代碼已經經過大量測試和調試,並且知道如何將其導出到所有的目標平台上。

  Java平台有一個用於和本地C、C++代碼進行互操作的API,稱為Java本地接口(JNI)。下面將舉例討論Linux平台下的JNI編程。

1. 創建java類文件

  創建一個nativeTest包,在包下新建HelloNative.java文件。

 1 package nativeTest;
 2 
 3 /**
 4  * Created by jiax on 2016/12/30.
 5  */
 6 public class HelloNative {
 7     // 靜態初始化代碼塊,保證虛擬機在第一次使用該類時就會裝載庫
 8     static {
 9         System.loadLibrary( "HelloNative" );
10     }
11 
12     // native 關鍵字表示本地方法,提醒編譯器該方法將在外部定義
13     public static native void greeting();
14 
15     // 測試greeting()函數
16     public static void main(String[] args) {
17         greeting();
18     }
19 }

2. 生成.h頭文件

  使用以下命令生成一個C的頭文件,nativeTest_HelloNative.h

1 javac HelloNative.java
2 cd ..
3 javah nativeTest.HelloNative

  生成的nativeTest_HelloNative.h如下:

 1 /* DO NOT EDIT THIS FILE - it is machine generated */
 2 #include <jni.h>
 3 /* Header for class nativeTest_HelloNative */
 4 
 5 #ifndef _Included_nativeTest_HelloNative
 6 #define _Included_nativeTest_HelloNative
 7 #ifdef __cplusplus
 8 extern "C" {
 9 #endif
10 /*
11  * Class:     nativeTest_HelloNative
12  * Method:    greeting
13  * Signature: ()V
14  */
15 JNIEXPORT void JNICALL Java_nativeTest_HelloNative_greeting
16   (JNIEnv *, jclass);
17 
18 #ifdef __cplusplus
19 }
20 #endif
21 #endif
nativeTest_HelloNative.h

  這個文件是在nativeTest文件夾外生成的,需要拖到nativeTest文件夾里面。  

3. 創建.c文件

  新建一個HelloNative.c文件,寫出greeting()函數的實現代碼。

1 #include <stdio.h>
2 #include "nativeTest_HelloNative.h"
3 
4 JNIEXPORT void JNICALL Java_nativeTest_HelloNative_greeting(JNIEnv *env, jobject c1) {
5     printf("Hello Native!!\n");
6 }

4. 編譯一個動態鏈接庫

  使用Linux下的gcc編譯器,命令如下:

gcc -fPIC -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -shared -o libHelloNative.so HelloNative.c

  生成libMyNative.so文件,此時整個nativeTest目錄文件結構如下:

5. 運行測試

  輸入如下命令運行HelloNative.class文件。

java nativeTest.HelloNative 

  如果出現如下錯誤:

  則需要把libHelloNative.so所在文件夾加入java.library.path,使用命令:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:..../nativeTest

  最終結果如下。

 6 總結

  總的來說,將一個本地方法鏈接到Java程序中需要經過以下5個步驟:

  1. 在Java類中聲明一個本地方法;
  2. 運行javah以獲得包含該方法的C聲明的頭文件;
  3. 用C實現該本地方法;
  4. 將代碼置於共享類庫中;
  5. 在Java程序中加載該類庫。

附錄——本文中用到的工具版本

JDK——1.8.0_111

gcc——4.8.5


免責聲明!

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



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