欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JAVA中調(diào)用C語言函數(shù)的實現(xiàn)方式

 更新時間:2023年08月02日 09:14:39   作者:豬哥-嵌入式  
這篇文章主要介紹了JAVA中調(diào)用C語言函數(shù)的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

背景知識

本地代碼

在JAVA中使用其他語言的代碼(如C/C++)稱為本地代碼。

歷史原因

JAVA的早期階段,很多人認(rèn)為使用C和C++來加速JAVA應(yīng)用中的關(guān)鍵部分是個好主意,但是實際上,雖然JAVA的代碼確實沒有純C的運行快,但是JAVA平臺實現(xiàn)要更快,也更穩(wěn)定。

本地代碼的應(yīng)用場景

本地代碼,比如C,對于跨平臺需求,需要針對支持的平臺提供單獨的本地類庫,而且使用C/C++編寫的代碼沒有對通過使用無效指針?biāo)斐傻膬?nèi)存腹瀉提供任何包含,比如內(nèi)存回收等,所以會容易破壞程序。

因此,只有在必要的時候才使用本地代碼,如下三種場景:

  • 1.應(yīng)用需要訪問的系統(tǒng)特性和設(shè)備通過JAVA平臺無法實現(xiàn)。
  • 2.已經(jīng)有了大量的測試過和調(diào)試過的用另一種語言編寫的代碼,比如圖像算法,并且知道如何將其導(dǎo)出到所有的目標(biāo)平臺上。
  • 3.通過基準(zhǔn)測試,編寫的JAVA代碼比其他語言編寫的等價代碼要慢。

JNI

JNI是Java Native Interface的縮寫,JNI是JAVA平臺專門用于和本地C代碼進(jìn)行相互操作的API,稱為JAVA本地接口。

JNI開發(fā)流程

  • 1.在JAVA中先聲明一個native方法。
  • 2.通過javac -h或javah -jni命令導(dǎo)出JNI使用的C頭頭文件。
  • 3.使用C實現(xiàn)本地方法。
  • 4.將本地代碼變異成動態(tài)庫,windows下是.dll文件,linux下是.so文件。
  • 5.在JAVA程序中加載步驟4中生成的類庫,執(zhí)行JAVA程序,最終實現(xiàn)JAVA本地代碼。

JNI頭文件規(guī)則

在JAVA中,調(diào)用本地代碼,需要實現(xiàn)本地代碼,需要編寫一個相應(yīng)的C函數(shù),而C函數(shù)需要按照J(rèn)AVA虛擬機的規(guī)則來實現(xiàn),其規(guī)則如下:

  • 1.使用完成的JAVA方法名,比如上例中,HelloNative.greeting,如果該類屬于某個包,還需要在前面添加包名稱,比如com.horstmann.HelloNative.greeting.
  • 2.用下劃線’_‘替換掉1中的所有’.’,然后添加上Java_前綴,比如:Java_HelloNative_greeting或Java_com_horstmann_HelloNative_greeting
  • 3.如果類名中含有非ASCII字母或數(shù)字,如’_’,’$‘或大于’\u007F’的Unicode字符,用_0xxxx來替代,xxxx是該字符的Unicode值的4個十六進(jìn)制數(shù)序列。

示例

本例中,通過簡單的打印功能C函數(shù)來舉例,在C中使用printf來實現(xiàn)某個打印函數(shù),在JAVA中調(diào)用該功能函數(shù)。

1. 使用native創(chuàng)建一個本地方法

JAVA中使用關(guān)鍵字native表示本地方法,在JAVA類中聲明一個方法,我們先創(chuàng)建一個HelloNative類,

代碼如下:

public class HelloNative {
    public static native void greeting();
}

2. 使用javac -h生成頭文件

使用 -h 標(biāo)志運行javac (java 編譯工具),提供頭文件存放目錄,實現(xiàn)對應(yīng)頭文件的生成。

命令代碼如下:

javac -h ./ HelloNative.java

運行上述命令后,就會在./ (當(dāng)前目錄)下自動生成一個名為 HelloNative.h的頭文件,

頭文件內(nèi)容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloNative */
#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloNative
 * Method:    greeting
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif

其中JNIEXPORT和JNICALL為宏定義,在頭文件jni.h中定義,jni.h在JDK安裝包中已經(jīng)包含。

他們的作用是為自動裝在庫的導(dǎo)出函數(shù)表明了依賴于編譯器的說明符。

3. 編寫本地方法的C代碼

我們需要根據(jù)頭文件中本地方法的聲明原型,使用C實現(xiàn),

程序如下:

#include <stdio.h>
#include "HelloNative.h"
JNIEXPORT void JNICALL Java_HelloNative_greeting(JNIEnv *env, jclass cl)
{
    printf("this is hello native .c printf\n");
}

上述代碼中,include了步驟2生成的頭文件,另外補充了JNIEnv和jclass,默認(rèn)的參數(shù)。

4. 在linux下,編寫該C代碼的動態(tài)庫

需要說明的是,由于該C代碼引用了jdk中的 jni.h頭文件,所以生成動態(tài)庫時,需要引用JDK的頭文件位置,

命令碼如下:

gcc -fPIC -I/opt/ctools/jdk1.8.0_301/include/ -I/opt/ctools/jdk1.8.0_301/include/linux/ -shared -o libHelloNative.so HelloNative.c

其中/opt/ctools/jdk1.8.0_301/include/ 和 /opt/ctools/jdk1.8.0_301/include/linux為依賴jdk的頭文件目錄。

編譯生成了 libHelloNative.so 共享庫。

5. 在JAVA程序中加載步驟5中生成的類庫,執(zhí)行

在JAVA程序中,通過System.loadLibrary方法調(diào)用動態(tài)庫,我們再編寫一個HelloNativeTest測試類,

代碼如下:

public class HelloNativeTest {
	public static void main(String[] args)
	{
		HelloNative.greeting();
	}
	static
	{
		System.loadLibrary("HelloNative");
	}
}

使用javac 編譯該測試類

javac HelloNativeTest.java

將步驟4中生成的動態(tài)庫添加到庫路徑中,命令如下:

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

編譯生成HelloNativeTest.class 字節(jié)碼, 使用java命令執(zhí)行

java HelloNativeTest

執(zhí)行命令結(jié)果如下:

this is hello native .c printf

至此就實現(xiàn)了在JAVA中調(diào)用C本地代碼的完整示例。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java中注解的實現(xiàn)原理詳解

    java中注解的實現(xiàn)原理詳解

    這篇文章主要介紹了java中注解的實現(xiàn)原理詳解,注解也叫元數(shù)據(jù),例如我們常見的@Override和@Deprecated,注解是JDK1.5版本開始引入的一個特性,用于對代碼進(jìn)行說明,可以對包、類、接口、字段、方法參數(shù)、局部變量等進(jìn)行注解,需要的朋友可以參考下
    2023-10-10
  • Java-lambda表達(dá)式入門看這一篇就夠了

    Java-lambda表達(dá)式入門看這一篇就夠了

    lambda表達(dá)式最簡單的作用就是用于簡化創(chuàng)建匿名內(nèi)部類對象,Lambda表達(dá)式是一個可傳遞的代碼塊,可以在以后執(zhí)行一次或多次,下面通過本文給大家介紹Java-lambda表達(dá)式入門教程,感興趣的朋友一起看看吧
    2021-05-05
  • 詳解Eclipse 字體、字號的設(shè)置、最佳字體推薦

    詳解Eclipse 字體、字號的設(shè)置、最佳字體推薦

    這篇文章主要介紹了Eclipse 字體、字號的設(shè)置、最佳字體推薦,需要的朋友可以參考下
    2020-09-09
  • Java實現(xiàn)猜數(shù)程序

    Java實現(xiàn)猜數(shù)程序

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)猜數(shù)程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • 淺談關(guān)于spring profile的誤解

    淺談關(guān)于spring profile的誤解

    這篇文章主要介紹了淺談關(guān)于spring profile的誤解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • Spring?MVC?請求映射路徑的配置實現(xiàn)前后端交互

    Spring?MVC?請求映射路徑的配置實現(xiàn)前后端交互

    在Spring?MVC中,請求映射路徑是指與特定的請求處理方法關(guān)聯(lián)的URL路徑,這篇文章主要介紹了Spring?MVC?請求映射路徑的配置,實現(xiàn)前后端交互,需要的朋友可以參考下
    2023-09-09
  • java和 javaw 及 javaws的區(qū)別解析

    java和 javaw 及 javaws的區(qū)別解析

    這篇文章主要介紹了java和 javaw 及 javaws的區(qū)別解析,本文通過實例給大家詳細(xì)介紹,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Java使用遞歸法解決漢諾塔問題的代碼示例

    Java使用遞歸法解決漢諾塔問題的代碼示例

    這篇文章主要介紹了Java使用遞歸法解決漢諾塔問題的代碼示例,漢諾塔問題是使用遞歸解決問題的經(jīng)典范例,用到的算法非常簡單,需要的朋友可以參考下
    2016-04-04
  • Java事件處理機制(自定義事件)實例詳解

    Java事件處理機制(自定義事件)實例詳解

    這篇文章主要介紹了Java事件處理機制(自定義事件)實例詳解的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • spring boot整合CAS配置詳解

    spring boot整合CAS配置詳解

    這篇文章主要介紹了spring boot整合CAS配置詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05

最新評論