導航:首頁 > 操作系統 > jnihlinux

jnihlinux

發布時間:2023-05-18 17:20:29

java jni 怎麼在windows環境中編譯linux下的so文件

可以直接在android工程下使用,因為android就是linux內核。

② linux環境java如何調用so文件

用JNI實現
實例:

創建HelloWorld.java
class HelloWorld
{
private native void print();
public staticvoid main(String[] args)
{
new HelloWorld().print();
}

static
{
System.loadLibrary("HelloWorld");
}
}
注意print方法的聲明,關鍵字native表明該方法是一個原生代碼實現的。另外注意static代碼段的System.loadLibrary調用,這段代碼表示在程序載入的時候,自動載入libHelloWorld.so庫。
編譯HelloWorld.java
在命令行中運行如下命令:
javac HelloWorld.java
在當前文件夾編譯生成HelloWorld.class。
生成HelloWorld.h
在命令行中運行如下命令:
javah -jni HelloWorld
在當前文件夾中會生成HelloWorld.h。打開HelloWorld.h將會發現如下代碼:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_print
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
該文件中包含了一個函數Java_HelloWorld_print的聲明。這裡麵包含兩個參數,非常重要,後面講實現的時候會講到。
實現HelloWorld.c
創建HelloWorld.c文件輸入如下的代碼:
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"

JNIEXPORT void JNICALL

Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
}
注意必須要包含jni.h頭文件,該文件中定義了JNI用到的各種類型,宏定義等。
另外需要注意Java_HelloWorld_print的兩個參數,本例比較簡單,不需要用到這兩個參數。但是這兩個參數在JNI中非常重要。
env代表java虛擬機環境,Java傳過來的參數和c有很大的不同,需要調用JVM提供的介面來轉換成C類型的,就是通過調用env方法來完成轉換的。
obj代表調用的對象,相當於c++的this。當c函數需要改變調用對象成員變數時,可以通過操作這個對象來完成。
編譯生成libHelloWorld.so
在Linux下執行如下命令來完成編譯工作:
cc -I/usr/lib/jvm/java-6-sun/include/linux/
-I/usr/lib/jvm/java-6-sun/include/
-fPIC -shared -o libHelloWorld.so HelloWorld.c
在當前目錄生成libHelloWorld.so。注意一定需要包含Java的include目錄(請根據自己系統環境設定),因為Helloworld.c中包含了jni.h。
另外一個值得注意的是在HelloWorld.java中我們LoadLibrary方法載入的是
「HelloWorld」,可我們生成的Library卻是libHelloWorld。這是Linux的鏈接規定的,一個庫的必須要是:lib+庫
名+.so。鏈接的時候只需要提供庫名就可以了。
運行Java程序HelloWorld
大功告成最後一步,驗證前面的成果的時刻到了:
java HelloWorld
如果你這步發生問題,如果這步你收到java.lang.UnsatisfiedLinkError異常,可以通過如下方式指明共享庫的路徑:
java -Djava.library.path='.' HelloWorld
當然還有其他的方式可以指明路徑請參考《在Linux平台下使用JNI》。
我們可以看到久違的「Hello world!」輸出了。

③ linux java 調用C++方法 編譯動態庫文件.so時找不到jni.h

用 sudo find / -name jni.h -print
命令,就會打出路徑

④ Linux環境下java調用C

你的JNI 寫錯了吧

java里的 char和 C的char完全不是一回事

java里你要寫 stringjava_encryptpswd(string Password, string EncryptedKey );

生成的 C頭文件,應該是 jstring java_encryptpswd(JEnvi* pEnvi,jstring Password,jstring EncryptedKey)

我手寫的,沒查資料握仿尺,大概是這樣。。

然後第一個參數是當大行前虛擬機事例,裡面有很多可用的函數

後面兩個是java里字元串結構,在C裡面的表示法, 其實它就是指針而已。

然後你可以用pEnvi里的函數,將java的string,轉化成 c的string。

然後調用 C的頭文件的函數,得到結果,在組裝成java的字元串。

比如段高例子:

我要用C來實現 java的字元串定位。

No.1 定義java的本地介面
public native String NAConvert(String arg1,String arg2);

No.2 生成頭文件
JNIEXPORT jstring JNICALL Java_com_test_mainandroid_MainAndroidNative_NAConvert
(JNIEnv *, jobject, jstring, jstring);

No.3 自己創建一個實現文件,實現上面函數
jstring Java_com_test_mainandroid_MainAndroidNative_NAConvert
(JNIEnv* env, jobject obj, jstring arg1, jstring arg2)
{
jsize len = env->GetStringLength(arg1);
jchar* pBuf = new jchar[len+1];
env->GetStringRegion(arg1,0,len,pBuf);

jclass m = env->FindClass("java/lang/String");

jmethodID mid = env->GetMethodID(m,"charAt","(I)C");

jchar c = env->CallCharMethod(arg1,mid,1);

return arg1 ;
}

第一個是虛擬機事例指針,第二個參數是介面方法所在對象的 this。
第三個及以後才是你的介面的參數。
java里傳入的所有對象參數,在C裡面都是句柄。必須要用第一個參數env才能解析其中含義。

⑤ 一文搞懂 , Linux內核—— 同步管理(下)

上面講的自旋鎖,信號量和互斥鎖的實現,都是使用了原子操作指令。由於原子操作會 lock,當線程在多個 CPU 上爭搶進入臨界區的時候,都會操作那個在多個 CPU 之間共享的數據 lock。CPU 0 操作了 lock,為了數據的一致性,CPU 0 的操作會導致其他 CPU 的 L1 中的 lock 變成 invalid,在隨後的來自其他 CPU 對 lock 的訪問會導致 L1 cache miss(更准確的說是communication cache miss),必須從下一個 level 的 cache 中獲取。

這就會使緩存一致性變得很糟,導致性能下降。所以內核提供一種新的同步方式:RCU(讀-復制-更新)。

RCU 解決了什麼

RCU 是讀寫鎖的高性能版本,它的核心理念是讀者訪問的同時,寫者可以更新訪問對象的副本,但寫者需要等待所有讀者完成訪問之後,才能刪除老對象。讀者沒有任何同步開銷,而寫者的同步開銷則取決於使用的寫者間同步機制。

RCU 適用於需要頻繁的讀取數據,而相應修改數據並不多的情景,例如在文件系統中,經常需要查找定位目錄,而對目錄的修改相對來說並不多,這就是 RCU 發揮作用的最佳場景。

RCU 例子

RCU 常用的介面如下圖所示:

為了更好的理解,在剖析 RCU 之前先看一個例子:

#include<linux/kernel.h>#include<linux/mole.h>#include<linux/init.h>#include<linux/slab.h>#include<linux/spinlock.h>#include<linux/rcupdate.h>#include<linux/kthread.h>#include<linux/delay.h>structfoo{inta;structrcu_headrcu;};staticstructfoo*g_ptr;staticintmyrcu_reader_thread1(void*data)//讀者線程1{structfoo*p1=NULL;while(1){if(kthread_should_stop())break;msleep(20);rcu_read_lock();mdelay(200);p1=rcu_dereference(g_ptr);if(p1)printk("%s: read a=%d\n",__func__,p1->a);rcu_read_unlock();}return0;}staticintmyrcu_reader_thread2(void*data)//讀者線程2{structfoo*p2=NULL;while(1){if(kthread_should_stop())break;msleep(30);rcu_read_lock();mdelay(100);p2=rcu_dereference(g_ptr);if(p2)printk("%s: read a=%d\n",__func__,p2->a);rcu_read_unlock();}return0;}staticvoidmyrcu_del(structrcu_head*rh)//回收處理操作{structfoo*p=container_of(rh,structfoo,rcu);printk("%s: a=%d\n",__func__,p->a);kfree(p);}staticintmyrcu_writer_thread(void*p)//寫者線程{structfoo*old;structfoo*new_ptr;intvalue=(unsignedlong)p;while(1){if(kthread_should_stop())break;msleep(250);new_ptr=kmalloc(sizeof(structfoo),GFP_KERNEL);old=g_ptr;*new_ptr=*old;new_ptr->a=value;rcu_assign_pointer(g_ptr,new_ptr);call_rcu(&old->rcu,myrcu_del);printk("%s: write to new %d\n",__func__,value);value++;}return0;}staticstructtask_struct*reader_thread1;staticstructtask_struct*reader_thread2;staticstructtask_struct*writer_thread;staticint__initmy_test_init(void){intvalue=5;printk("figo: my mole init\n");g_ptr=kzalloc(sizeof(structfoo),GFP_KERNEL);reader_thread1=kthread_run(myrcu_reader_thread1,NULL,"rcu_reader1");reader_thread2=kthread_run(myrcu_reader_thread2,NULL,"rcu_reader2");writer_thread=kthread_run(myrcu_writer_thread,(void*)(unsignedlong)value,"rcu_writer");return0;}staticvoid__exitmy_test_exit(void){printk("goodbye\n");kthread_stop(reader_thread1);kthread_stop(reader_thread2);kthread_stop(writer_thread);if(g_ptr)kfree(g_ptr);}MODULE_LICENSE("GPL");mole_init(my_test_init);mole_exit(my_test_exit);

執行結果是:

myrcu_reader_thread2:reada=0myrcu_reader_thread1:reada=0myrcu_reader_thread2:reada=0myrcu_writer_thread:writetonew5myrcu_reader_thread2:reada=5myrcu_reader_thread1:reada=5myrcu_del:a=0

RCU 原理

可以用下面一張圖來總結,當寫線程 myrcu_writer_thread 寫完後,會更新到另外兩個讀線程 myrcu_reader_thread1 和 myrcu_reader_thread2。讀線程像是訂閱者,一旦寫線程對臨界區有更新,寫線程就像發布者一樣通知到訂閱者那裡,如下圖所示。

寫者在拷貝副本修改後進行 update 時,首先把舊的臨界資源數據移除(Removal);然後把舊的數據進行回收(Reclamation)。結合 API 實現就是,首先使用 rcu_assign_pointer 來移除舊的指針指向,指向更新後的臨界資源;然後使用 synchronize_rcu 或 call_rcu 來啟動 Reclaimer,對舊的臨界資源進行回收(其中 synchronize_rcu 表示同步等待回收,call_rcu 表示非同步回收)。

為了確保沒有讀者正在訪問要回收的臨界資源,Reclaimer 需要等待所有的讀者退出臨界區,這個等待的時間叫做寬限期(Grace Period)。

Grace Period

中間的黃色部分代表的就是 Grace Period,中文叫做寬限期,從 Removal 到 Reclamation,中間就隔了一個寬限期,只有當寬限期結束後,才會觸發回收的工作。寬限期的結束代表著 Reader 都已經退出了臨界區,因此回收工作也就是安全的操作了。

寬限期是否結束,與 CPU 的執行狀態檢測有關,也就是檢測靜止狀態 Quiescent Status。

Quiescent Status

Quiescent Status,用於描述 CPU 的執行狀態。當某個 CPU 正在訪問 RCU 保護的臨界區時,認為是活動的狀態,而當它離開了臨界區後,則認為它是靜止的狀態。當所有的 CPU 都至少經歷過一次 Quiescent Status 後,寬限期將結束並觸發回收工作。

因為 rcu_read_lock 和 rcu_read_unlock 分別是關閉搶占和打開搶占,如下所示:

staticinlinevoid__rcu_read_lock(void){preempt_disable();}

staticinlinevoid__rcu_read_unlock(void){preempt_enable();}

所以發生搶占,就說明不在 rcu_read_lock 和 rcu_read_unlock 之間,即已經完成訪問或者還未開始訪問。

Linux 同步方式的總結

資料免費領

學習直通車

⑥ java使用JNI調用VC6.0編寫的動態鏈接庫dll,如何移植到linux環境下使用

你想要的應該基本不可能實現了,gpsun.lib是在window下生成的靜態庫,是不能在linux上直接調用的,襲岩如果你清楚gpsin的實現,可以在linux下編一個自己的靜態庫,是以.a結尾的拍亂御,然後在linux上編譯.so文陪局件時將這個.a文件鏈接進去,最後就可以用jni去調用了

⑦ 在java本地方法調用中,jni.h這個文件起到的作用是什麼它和jniEvn是什麼關系為什麼必須要引入jni.h...

簡單的回答就是需要本地庫函數。
從Java原理來基叢講,你還要看下文:
本地方法調用就是 Java Native Interface(JNI),JNI最終的目的是在Java端調用本地系統的方法,Java之所以跨平台是因為JVM的設計是基於堆棧的,而像C、C++是基於寄存器的,寄存器應該懂吧,每個硬體的寄存器都不相同。JAVA class類運宏瞎行在搏絕櫻JVM中,即在堆棧(邏輯的數據結構)中,這個堆棧的數據結構都一樣,所以就JAVA就有了跨平台。
而有的時候JAVA想直接對計算機硬體操作,即直接對寄存器操作,那麼就需要相應的本地庫,jni.h就是本地庫。這個本地庫內的API都是完全基於寄存器來操作的。
一個字一個字敲的,不知道我說的你明白沒?
如果你明白基於堆棧和寄存器的區別,理解JNI就沒問題了。

⑧ linux 常用命令大全

linux常用命令有pwd命令、cd命令、ls命令、cat命令、grep命令、touch命令、cp命令、mv命令、rm命令、rmdir命令等。

linux常用命令:

1、 pwd命令

該命令的英文解釋為print working directory(列印工作目錄)。輸入pwd命令,Linux會輸出當前目錄。

2、 cd命令

cd命令用來改變所在目錄。

cd / 轉到根目錄中

cd ~ 轉到/home/user用戶目錄下

cd /usr 轉到根目錄下的usr目錄中-------------絕對路徑

cd test 轉到當前目錄下的test子目錄中-------相對路徑

3、 ls命令

ls命令用來查看目錄的內容。 選項 含義 -a 列舉目錄中的全部文件,包括隱藏文件 -l 列舉目錄中的細節,包括許可權、所有者、組群、大小、創建日期、文件團缺是否是鏈接等 -f 列舉的文件顯示文件類型 -r 逆向,從後向前地列舉目錄中內容 -R 遞歸,該選項遞歸地列舉當前目錄下所有子目錄內的內容 -s 大小,按文件大小排序 -h 以人類可讀的方式顯示文件的大小,如用K、M、G作單位 ls -l examples.doc 列舉文件examples.doc的所有信息

4、 cat命令

cat命令可以用來合並文件,也可以用來在屏幕上顯示整個文件的內容。

cat snow.txt 該命令顯示文件snow.txt的內容,ctrl D退出cat。

5、 grep命令

grep命令的最大功能是在一堆文件中查找一個特定的字元串。

grep money test.txt

以上命令在test.txt中查找money這個字元串,grep查找是區分大小寫的。

6 、touch命令

touch命令用來創建新文件,他可以創建一個空白的文件,可以在其中添加文本和數據。

touch newfile 該命令創建一個名為newfile的空白文件。

7 、cp命令

cp命令用來拷貝文件,要復制文件,輸入命令:

cp

cp t.txt Document/t 該命令將把文件t.txt復制到Document目錄下,並命名為t。 選項 含義 -i 互動:如果文件將覆蓋目標中的文件,他會提示確認 -r 遞歸:這個選項會復制整個目錄樹、子目錄以及其他 -v 詳細:顯示文件的復制進度

8 、mv命令

mv命令用來移動文件。 選項 說明 -i 互動:如果選擇的文件會覆蓋目標中的文件,他會提示確認 -f 強制:它會超昌御越互動模式,不提示地移動文件,屬於很危險的選項 -v 詳細:顯示文件的移動進度

mv t.txt Document 把文件t.txt 移動到目錄Document中。

9 、rm命令

rm命令用來刪除文件。 選項 說明 -i 互動:提示確認刪除 -f 強制:代替互塌迅辯動模式,不提示確認刪除 -v 詳細:顯示文件的刪除進度 -r 遞歸:將刪除某個目錄以及其中所有的文件和子目錄

rm t.txt 該命令刪除文件t.txt

10、 rmdir命令

rmdir命令用來刪除目錄。

linux常用命令有pwd命令、cd命令、ls命令、cat命令、grep命令、touch命令、cp命令、mv命令、rm命令、rmdir命令等。

linux常用命令:

1、 pwd命令

該命令的英文解釋為print working directory(列印工作目錄)。輸入pwd命令,Linux會輸出當前目錄。

2、 cd命令

cd命令用來改變所在目錄。

cd / 轉到根目錄中

cd ~ 轉到/home/user用戶目錄下

cd /usr 轉到根目錄下的usr目錄中-------------絕對路徑

cd test 轉到當前目錄下的test子目錄中-------相對路徑

3、 ls命令

ls命令用來查看目錄的內容。 選項 含義 -a 列舉目錄中的全部文件,包括隱藏文件 -l 列舉目錄中的細節,包括許可權、所有者、組群、大小、創建日期、文件是否是鏈接等 -f 列舉的文件顯示文件類型 -r 逆向,從後向前地列舉目錄中內容 -R 遞歸,該選項遞歸地列舉當前目錄下所有子目錄內的內容 -s 大小,按文件大小排序 -h 以人類可讀的方式顯示文件的大小,如用K、M、G作單位 ls -l examples.doc 列舉文件examples.doc的所有信息

4、 cat命令

cat命令可以用來合並文件,也可以用來在屏幕上顯示整個文件的內容。

cat snow.txt 該命令顯示文件snow.txt的內容,ctrl D退出cat。

5、 grep命令

grep命令的最大功能是在一堆文件中查找一個特定的字元串。

grep money test.txt

以上命令在test.txt中查找money這個字元串,grep查找是區分大小寫的。

6 、touch命令

touch命令用來創建新文件,他可以創建一個空白的文件,可以在其中添加文本和數據。

touch newfile 該命令創建一個名為newfile的空白文件。

7 、cp命令

cp命令用來拷貝文件,要復制文件,輸入命令:

cp

cp t.txt Document/t 該命令將把文件t.txt復制到Document目錄下,並命名為t。 選項 含義 -i 互動:如果文件將覆蓋目標中的文件,他會提示確認 -r 遞歸:這個選項會復制整個目錄樹、子目錄以及其他 -v 詳細:顯示文件的復制進度

8 、mv命令

mv命令用來移動文件。 選項 說明 -i 互動:如果選擇的文件會覆蓋目標中的文件,他會提示確認 -f 強制:它會超越互動模式,不提示地移動文件,屬於很危險的選項 -v 詳細:顯示文件的移動進度

mv t.txt Document 把文件t.txt 移動到目錄Document中。

9 、rm命令

rm命令用來刪除文件。 選項 說明 -i 互動:提示確認刪除 -f 強制:代替互動模式,不提示確認刪除 -v 詳細:顯示文件的刪除進度 -r 遞歸:將刪除某個目錄以及其中所有的文件和子目錄

rm t.txt 該命令刪除文件t.txt

10、 rmdir命令

rmdir命令用來刪除目錄。

⑨ android中使用jni可以調用linux操作系統下的庫嗎

可以調用,但是不能直接調用,要通並孝過代碼目的JNI去調游伏用,在JNI中導入頭文件,通過NDK編譯成功後即可。 NDK編譯步驟: 1.選擇 ndk 自帶的例子 hello-jni ,我的神蔽攜位於E:\android-ndk-r5\samples\hello-jni( 根據具體的安裝位置而定 ) 。 2.運行 cyg...

⑩ clion編譯jni,找不到jni.h的解決辦法

在windows環境下畢陪生成的動態庫是 dll
在linux下生成so
在mac下生成的是dylib
所以對於Android的開發者來說,還是要用ndk的工具
把在idea生成的.h文件粘貼到clion的項目中就可以了,
如果找不到jni.h可以在CMakeList.txt中添加對jni.h文件的引用
如下:

後面三行根據jdk的實際位置填寫,作用是導入jni相關的頭文件;其他的操作系統可能不完全一致

復制.h頭文件 com_shenby_jni_JniExample.h

實現該文件定義的函數 com_shenby_jni_JniExample.c

在CMakeList.txt中添加生成動態共項庫

add_library:生成一個庫,add_executable:生成一個可執行文件
hello:是生成共享庫的名字,前面會自動加上lib前綴,如這里windows生成的是 libhello.dll
SHARED:庫的類型為動態,windows上生成.dll,而STATIC 則是生成靜態庫,windows生成.a文件
com_shenby_jni_JniExample.c :c源文件,頌隱多個文件就添加在後面,切記不手櫻蠢能添加上面的com_shenby_jni_JniExample.h
文件,否則生成的庫中的函數為空

結果如下

就可以把該dll文件粘貼到idea的項目根目錄中運行了

閱讀全文

與jnihlinux相關的資料

熱點內容
區位碼加密 瀏覽:854
考編教師用什麼app 瀏覽:189
靜態面向對象編程語言 瀏覽:902
炒股密碼pdf 瀏覽:661
差分演算法有哪些 瀏覽:563
佳明怎麼配對安卓 瀏覽:245
用什麼app校對試卷 瀏覽:101
基於單片機的光控路燈 瀏覽:33
為什麼說安卓平板適配的軟體少 瀏覽:680
三國志下載pdf 瀏覽:689
為什麼單片機c語言 瀏覽:429
演算法一定有一個或多個輸入 瀏覽:252
浪潮伺服器貴州銷售雲主機 瀏覽:850
amdlinux顯卡安裝 瀏覽:572
泰海科技雲伺服器如何卸載 瀏覽:126
有密碼打開excel加密 瀏覽:823
java生成重復字元 瀏覽:284
串口伺服器有什麼用 瀏覽:331
linux安裝red5 瀏覽:295
單片機中斷時入口地址作用 瀏覽:150