最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

背景知識(shí)

本地代碼

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

歷史原因

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

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

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

因此,只有在必要的時(shí)候才使用本地代碼,如下三種場(chǎng)景:

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

JNI

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

JNI開發(fā)流程

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

JNI頭文件規(guī)則

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

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

示例

本例中,通過(guò)簡(jiǎn)單的打印功能C函數(shù)來(lái)舉例,在C中使用printf來(lái)實(shí)現(xiàn)某個(gè)打印函數(shù),在JAVA中調(diào)用該功能函數(shù)。

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

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

代碼如下:

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

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

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

命令代碼如下:

javac -h ./ HelloNative.java

運(yùn)行上述命令后,就會(huì)在./ (當(dāng)前目錄)下自動(dòng)生成一個(gè)名為 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òng)裝在庫(kù)的導(dǎo)出函數(shù)表明了依賴于編譯器的說(shuō)明符。

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

我們需要根據(jù)頭文件中本地方法的聲明原型,使用C實(shí)現(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生成的頭文件,另外補(bǔ)充了JNIEnv和jclass,默認(rèn)的參數(shù)。

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

需要說(shuō)明的是,由于該C代碼引用了jdk中的 jni.h頭文件,所以生成動(dòng)態(tài)庫(kù)時(shí),需要引用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 共享庫(kù)。

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

在JAVA程序中,通過(guò)System.loadLibrary方法調(diào)用動(dòng)態(tài)庫(kù),我們?cè)倬帉懸粋€(gè)HelloNativeTest測(cè)試類,

代碼如下:

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

使用javac 編譯該測(cè)試類

javac HelloNativeTest.java

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

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

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

java HelloNativeTest

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

this is hello native .c printf

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

總結(jié)

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

相關(guān)文章

  • Java中this調(diào)用會(huì)導(dǎo)致事務(wù)失效的深入分析

    Java中this調(diào)用會(huì)導(dǎo)致事務(wù)失效的深入分析

    在Java中this是一個(gè)非常重要的關(guān)鍵字,它表示當(dāng)前對(duì)象的引用,也就是說(shuō),當(dāng)你在某個(gè)類的實(shí)例方法或構(gòu)造器中時(shí),this指向調(diào)用該方法或創(chuàng)建的當(dāng)前對(duì)象實(shí)例,這篇文章主要介紹了Java中this調(diào)用會(huì)導(dǎo)致事務(wù)失效的相關(guān)資料,需要的朋友可以參考下
    2026-04-04
  • SpringBoot接口路徑重復(fù),啟動(dòng)服務(wù)器失敗的解決

    SpringBoot接口路徑重復(fù),啟動(dòng)服務(wù)器失敗的解決

    這篇文章主要介紹了SpringBoot接口路徑重復(fù),啟動(dòng)服務(wù)器失敗的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法

    Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法

    這篇文章主要介紹了Java基于Runtime調(diào)用外部程序出現(xiàn)阻塞的解決方法,是一個(gè)非常實(shí)用的技巧,需要的朋友可以參考下
    2014-09-09
  • Java連接Oracle數(shù)據(jù)庫(kù)實(shí)例解析

    Java連接Oracle數(shù)據(jù)庫(kù)實(shí)例解析

    數(shù)據(jù)庫(kù)的操作是當(dāng)前系統(tǒng)開發(fā)必不可少的開發(fā)部分之一。接下來(lái)通過(guò)本文給大家介紹Java連接Oracle數(shù)據(jù)庫(kù)實(shí)例解析,非常不錯(cuò)具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-06-06
  • Java預(yù)防SQL注入的具體實(shí)踐方法

    Java預(yù)防SQL注入的具體實(shí)踐方法

    在?Java?中預(yù)防?SQL?注入的核心是?避免直接拼接?SQL?語(yǔ)句,并通過(guò)參數(shù)化查詢、ORM?框架和嚴(yán)格的輸入驗(yàn)證來(lái)實(shí)現(xiàn)安全防護(hù),以下是具體實(shí)踐方法,感興趣的小伙伴跟著小編一起來(lái)看看吧
    2025-01-01
  • springMVC盜鏈接詳解

    springMVC盜鏈接詳解

    這篇文章主要為大家詳細(xì)介紹了SpringMVC盜鏈接詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能給你帶來(lái)幫助
    2021-07-07
  • Java類中static{}的具體使用

    Java類中static{}的具體使用

    static{}(即static塊),會(huì)在類被加載的時(shí)候執(zhí)行且僅會(huì)被執(zhí)行一次,一般用來(lái)初始化靜態(tài)變量和調(diào)用靜態(tài)方法,本文主要介紹了Java類中static{}的具體使用,感興趣的可以了解一下
    2024-07-07
  • 最新評(píng)論

    句容市| 哈巴河县| 滦南县| 霍林郭勒市| 东乌珠穆沁旗| 镇巴县| 繁峙县| 西畴县| 永昌县| 山丹县| 闵行区| 西乌珠穆沁旗| 江口县| 大新县| 郑州市| 吉水县| 凉城县| 西宁市| 和政县| 鹿邑县| 芜湖县| 紫云| 延长县| 桐梓县| 宜兴市| 景泰县| 枝江市| 乐清市| 阿拉善左旗| 桓仁| 灵丘县| 翁牛特旗| 西青区| 三穗县| 潍坊市| 红桥区| 普兰县| 兴山县| 邢台市| 英德市| 邯郸县|