導航:首頁 > 編程語言 > javajni教程

javajni教程

發布時間:2022-05-02 01:58:28

㈠ 淺談如何用JNI的代碼調用java介面

對於本地函數
JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj)
{
cout<<"Hello Native Test !"<<endl;
}

JNIEnv類型代表Java環境。通過這個JNIEnv*指針,就可以對Java端的代碼進行操作。如,創建Java類得對象,調用Java對象的方法,獲取Java對象的屬性等。
JNIEnv的指針會被JNI傳送到本地方法的實現函數中來對Java端的代碼進行操作

JNIEnv類中的函數:
NewObject/NewString/New<TYPE>Array :new新對象
Get/Set<TYPE>Field:獲取屬性
Get/SetStatic<TYPE>Field :獲取靜態屬性
Call<TYPE>Method/CallStatic<TYPE>Method

㈡ 如何從C中調用Java函數使用JNI

1. 編寫並編譯J2C.java
import java.lang.management.ManagementFactory;

import java.lang.management.RuntimeMXBean;
public class J2C
{
static
{
try{
// 此處即為本地方法所在鏈接庫名
System.loadLibrary("j2c");
} catch(UnsatisfiedLinkError e)
{
System.err.println( "Cannot load J2C library:\n " +
e.toString() );
}
}
//聲明的本地方法
public static native int write2proc(int pid);
public static void main(String[] args){
//獲取本進程(即主線程)的pid
final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final String info = runtime.getName();
final int index = info.indexOf("@");

if (index != -1) {
final int pid = Integer.parseInt(info.substring(0, index));
System.out.println(info);
System.out.println(pid);
write2proc(pid);
}

try{
Thread.sleep(8000);
} catch(InterruptedException e){
e.printStackTrace();
}
}
}

note:Java程序中System.loadLibrary參數名表示要載入的C/C++共享庫,第6步生成的共享庫名必須與該參數一致,即System.loadLibrary(Name) 對應共享庫名libName.so (共享庫名必須以lib開頭)
2. 生成C頭文件J2C.h:javah J2C
/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>
/* Header for class J2C */

#ifndef _Included_J2C
#define _Included_J2C
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: J2C
* Method: write2proc
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_J2C_write2proc
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif

note:1. 頭文件自動生成,不要修改它;
2. 函數JNIEXPORT jint JNICALL Java_J2C_write2proc(JNIEnv *, jclass, jint);
按照注釋的說明是在J2C.java文件的類J2C的方法write2proc處定義,故C程序的實現函數必須與該處簽名一致;
3. 編寫C程序J2C.c
#include <stdio.h>

#include "J2C.h"
JNIEXPORT int JNICALL Java_J2C_write2proc(JNIEnv * env, jobject arg, jint pid)
{
printf("current pid is %d\n", pid);
return 0;
}

4. 編譯C程序

因為C程序里#include "J2C.h"而J2C.h又#include <jni.h>, 而gcc裡面默認環境並不知道jni.h是什麼東西,故編譯時需要告訴編譯器jni.h的位置( jni.h在jdk 的$JAVA_HOME/include下面),所以才有了上面的編譯參數;
因為使用gcc編譯得到動態庫,在jni調用的時候,某些情況會有異常, 可嘗試改用g++。
總結
1. Java中方法的原型聲明與C/C++對應的實現文件定義必須一致(可以通過自動生成的C/C++頭文件來比較),尤其是類名和方法名;
2. Java中System.loadLibrary()載入的共享庫名必須與後面C/C++生成的共享庫名一致。

㈢ java 調用動態鏈接庫(jni方式調用dll文件)

jni 是由Java調用C/C++的動態鏈接庫 (DLL)。
所以把.class-->.h-->dll ,想法是不正確的,
同時也違背了Jni的初衷。
Dll是由C/C++生成的。

以前的一個項目用到了Java調用C/C++的DLL,所以對這個還算熟悉。
那個dLL是由C++程序員寫的,在Microsoft Visual C++ 6.0編輯器中可以生成。然後由Java程序員用JNI來調用DLL裡面實現的功能(方法)。

㈣ java里的native方法怎麼運行

你先寫個native方法的申明在你的類,如
class MyClass{
public native void sayHello();
}
然後javac編譯,
再javah -jni (你的java源文件路徑)
它會知道生成一個c的頭文件,再在vc(或者vs)新建一個動態鏈接庫(dll)工程,include,再實現你的函數,編譯出dll文件,設定一下classpath,讓jvm找得到dll,java運行就行了

㈤ JAVA 裡面如何 使用jni 給個例子 加 解釋。謝謝

JAVA以其跨平台的特性深受人們喜愛,而又正由於它的跨平台的目的,使得它和本地機器的各種內部聯系變得很少,約束了它的功能。解決JAVA對本地操作的一種方法就是JNI。
JAVA通過JNI調用本地方法,而本地方法是以庫文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX機器上是SO文件形式)。通過調用本地的庫文件的內部方法,使JAVA可以實現和本地機器的緊密聯系,調用系統級的各介面方法。
簡單介紹及應用如下:
一、JAVA中所需要做的工作
在JAVA程序中,首先需要在類中聲明所調用的庫名稱,如下:
static {
System.loadLibrary(「goodluck」);
}

在這里,庫的擴展名字可以不用寫出來,究竟是DLL還是SO,由系統自己判斷。
還需要對將要調用的方法做本地聲明,關鍵字為native。並且只需要聲明,而不需要具 體實現。如下:
public native static void set(int i);
public native static int get();
然後編譯該JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就會生成C/C++的頭文件。
例如程序testdll.java,內容為:
public class testdll
{
static
{
System.loadLibrary("goodluck");
}
public native static int get();
public native static void set(int i);
public static void main(String[] args)
{
testdll test = new testdll();
test.set(10);
System.out.println(test.get());
}
}

用javac testdll.java編譯它,會生成testdll.class。
再用javah testdll,則會在當前目錄下生成testdll.h文件,這個文件需要被C/C++程序調用來生成所需的庫文件。
二、C/C++中所需要做的工作
對於已生成的.h頭文件,C/C++所需要做的,就是把它的各個方法具體的實現。然後編譯連接成庫文件即可。再把庫文件拷貝到JAVA程序的路徑下面,就可以用JAVA調用C/C++所實現的功能了。
接上例子。我們先看一下testdll.h文件的內容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class testdll */
#ifndef _Included_testdll
#define _Included_testdll
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: testdll
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);
/*
* Class: testdll
* Method: set
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
在具體實現的時候,我們只關心兩個函數原型
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); 和
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
這里JNIEXPORT和JNICALL都是JNI的關鍵字,表示此函數是要被JNI調用的。而jint是以JNI為中介使JAVA的int類型與本地的int溝通的一種類型,我們可以視而不見,就當做int使用。函數的名稱是JAVA_再加上java程序的package路徑再加函數名組成的。參數中,我們也只需要關心在JAVA程序中存在的參數,至於JNIEnv*和jclass我們一般沒有必要去碰它。
好,下面我們用testdll.cpp文件具體實現這兩個函數:
#include "testdll.h"
int i = 0;
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)
{
return i;
}
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)
{
i = j;
}
編譯連接成庫文件,本例是在WINDOWS下做的,生成的是DLL文件。並且名稱要與JAVA中需要調用的一致,這里就是goodluck.dll 。把goodluck.dll拷貝到testdll.class的目錄下,java testdll運行它,就可以觀察到結果了。

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

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

㈦ 如何用JNI技術提高Java的性能詳解

阻礙Java取得廣泛使用的一個首要因素是Java程序的運行效率。Java是介於解釋型和編譯型之間的一種語言,同樣的程序,假如用編譯型語言C來實現,其運行速度通常要比Java快一倍以上。Java具有平台無關性,這使人們在開發企業級使用的時刻總是把它作為首要候選方案之一,但是性能方面的因素又大大削弱了它的競爭力。為此,提高Java的性能就顯得十分主要。 疑問的提出 Sun公司及Java的支撐者們為提高Java的運行速度已經做出了許多全力,其中大多數集中在程序設計的要領和模式挑選方面。由於演算法和設計模式的優化是通用的,對Java有效的優化演算法和設計模式,對其他編譯語言也基本同樣適用,因此無法從根本上改動 Java程序與編譯型語言在執行效率方面的差別。 JIT(Just In Time,及時編譯)技能是個比較好的思想。它的基本原理是:最先議決 Java編譯器把Java源代碼編譯成平台無關的二進制位元組碼。然後在Java程序真實執行之前,系統議決 JIT編譯器把Java的位元組碼編譯為本地化機器碼。結尾,系統執行本地化機器碼,節省了對位元組碼實行解釋的時間。這樣做的優點是大大提高了Java程序的性能,縮短了載入程序的時間;同時,由於編譯的結果並不在程序運行間保存,因此也節約了存儲空間。缺點是由於JIT編譯器對所有的代碼都想優化,因此同樣也佔用了許多時間。 動態優化技能是提高Java性能的另一個嘗試。該技能試圖議決把Java源程序直接編譯成機器碼,以充分使用 Java動態編譯和靜態編譯技能來提高Java的性能。該要領把輸入的Java源碼或位元組碼轉換為經歷高度優化的可執行代碼和動態庫 (Windows中的. dll文件或Unix中的. so文件)。該技能能大大提高程序的性能,但卻破壞了Java的可移植性。 JNI技能 實際上,有一種通常為咱們忽視的技能能夠在很大程度上處理這個難題,那就是JNI(Java Native Interface, Java本地化要領 )。主張採用純Java的人們通常反對本地化代碼的運用,他們認為在Java程序執行的流程中調用C/C++程序會影響程序的可移植性和安全性。還有一些人認為JNI只是對過去混合編程技能的基本擴展,本來際目標是為了充分使用大量原有的C程序庫。 本來,咱們不必拘泥於嚴格的平台獨立性限定,因為採用JNI技能只是針對一些嚴重影響Java性能的代碼段,該部分可能只佔源程序的極少部分,所以幾乎能夠不思慮該部分代碼在主流平台之間移植的工作量。同時,也不必過分擔心類型匹配疑問,咱們完全能夠控制代碼不出現這種不正確。此外,也不必擔心安全控制疑問,因為Java安全模型已擴展為准許非系統類載入和調用本地點法。根據Java規范,從JDK 1. 2開始,FindClass將設法找到與當前的本地點法關聯的類載入器。假如平台有關代碼屬於一個系統類,則無需涉及任何類載入器; 否則,將調用適當的類載入器來載入和鏈接已命名的類。換句話說,假如在Java程序中直接調用C/C++語言產生的機器碼,該部分代碼的安全性就由Java虛擬機控制。

㈧ 怎麼用jni

·編寫帶有native聲明的方法的java類·使用javac命令編譯所編寫的java類·使用javah ?jni java類名生成擴展名為h的頭文件·使用C/C++實現本地方法·將C/C++編寫的文件生成動態連接庫·ok 1) 編寫java程序:這里以HelloWorld為例。 代碼1:class HelloWorld { public native void displayHelloWorld(); static { System.loadLibrary("hello"); } public static void main(String[] args) { new HelloWorld().displayHelloWorld(); } } 聲明native方法:如果你想將一個方法做為一個本地方法的話,那麼你就必須聲明改方法為native的,並且不能實現。其中方法的參數和返回值在後面講述。 Load動態庫:System.loadLibrary("hello");載入動態庫(我們可以這樣理解:我們的方法 displayHelloWorld()沒有實現,但是我們在下面就直接使用了,所以必須在使用之前對它進行初始化)這里一般是以static塊進行載入的。同時需要注意的是System.loadLibrary();的參數「hello」是動態庫的名字。2) 編譯 沒有什麼好說的了 javac HelloWorld.java 3) 生成擴展名為h的頭文件 javah ? jni HelloWorld 頭文件的內容: /* DO NOT EDIT THIS FILE - it is machine generated */ 1. include /* Header for class HelloWorld */ 1. ifndef _Included_HelloWorld 2. define _Included_HelloWorld 3. ifdef __cplusplus extern "C" { 1. endif /* * Class: HelloWorld * Method: displayHelloWorld * Signature: ()V * / JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject); 1. ifdef __cplusplus } 1. endif 2. endif (這里我們可以這樣理解:這個h文件相當於我們在java裡面的介面,這里聲明了一個 Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然後在我們的本地方法裡面實現這個方法,也就是說我們在編寫C/C++程序的時候所使用的方法名必須和這里的一致)。4) 編寫本地方法實現和由javah命令生成的頭文件裡面聲明的方法名相同的方法。 代碼2:1 #include "jni.h" 2 #include "HelloWorld.h" 3 //#include other headers 4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj) { printf("Hello world!\n"); return; } 注意代碼2中的第1行,需要將jni.h(該文件可以在%JAVA_HOME%/include文件夾下面找到)文件引入,因為在程序中的JNIEnv、 jobject等類型都是在該頭文件中定義的;另外在第2行需要將HelloWorld.h頭文件引入(我是這么理解的:相當於我們在編寫java程序的時候,實現一個介面的話需要聲明才可以,這里就是將HelloWorld.h頭文件裡面聲明的方法加以實現。當然不一定是這樣)。然後保存為 HelloWorldImpl.c就ok了。5) 生成動態庫 這里以在Windows中為例,需要生成dll文件。在保存HelloWorldImpl.c文件夾下面,使用VC的編譯器cl成。 cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll 注意:生成的dll文件名在選項-Fe後面配置,這里是hello,因為在HelloWorld.java文件中我們loadLibary的時候使用的名字是hello。當然這里修改之後那裡也需要修改。另外需要將-I%java_home%\include -I%java_home%\include\win32參數加上,因為在第四步裡面編寫本地方法的時候引入了jni.h文件。6) 運行程序 java HelloWorld就ok.下面是一個簡單的例子實現列印一句話的功能,但是用的c的printf最終實現。一般提供給java的jni介麵包括一個so文件(封裝了c函數的實現)和一個java文件(需要調用path的類)。1. JNI的目的是使java方法中能夠調用c實現的一些函數,比如以下的java類,就需要調用一個本地函數testjni(一般聲明為private native類型),首先需要創建文件weiqiong.java,內容如下:class weiqiong { static { System.loadLibrary("testjni");//載入靜態庫,test函數在其中實現 } private native void testjni(); //聲明本地調用 public void test() { testjni(); } public static void main(String args[]) { weiqiong haha = new weiqiong(); haha.test(); } }2.然後執行javac weiqiong.java,如果沒有報錯,會生成一個weiqiong.class。3.然後設置classpath為你當前的工作目錄,如直接輸入命令行:set classpath = weiqiong.class所在的完整目錄(如 c:\test)再執行javah weiqiong,會生成一個文件weiqiong.h文件,其中有一個函數的聲明如下:JNIEXPORT void JNICALL Java_weiqiong_testjni (JNIEnv *, jobject);4.創建文件testjni.c將上面那個函數實現,內容如下:1. include2. includeJNIEXPORT void JNICALL Java_weiqiong_testjni (JNIEnv *env, jobject obj) { printf("haha---------go into c!!!\n"); }5.為了生成.so文件,創建makefile文件如下:libtestjni.so:testjni.o makefile gcc -Wall -rdynamic -shared -o libtestjni.so testjni.o testjni.o:testjni.c weiqiong.h gcc -Wall -c testjni.c -I./ -I/usr/java/j2sdk1.4.0/include -I/usr/java/j2sdk1.4.0/include/linux cl: rm -rf *.o *.so 注意:gcc前面是tab空,j2sdk的目錄根據自己裝的j2sdk的具體版本來寫,生成的so文件的名字必須是loadLibrary的參數名前加「lib」。6.export LD_LIBRARY_PATH=.,由此設置library路徑為當前目錄,這樣java文件才能找到so文件。一般的做法是將so文件到本機的LD_LIBRARY_PATH目錄下。7.執行java weiqiong,列印出結果:「haha---------go into c!!!」在首次使用JNI的時候有些疑問,後來在使用中一一解決,下面就是這些問題的備忘:1。 java和c是如何互通的?其實不能互通的原因主要是數據類型的問題,jni解決了這個問題,例如那個c文件中的jstring數據類型就是java傳入的String對象,經過jni函數的轉化就能成為c的char*。對應數據類型關系如下表:Java 類型 本地c類型 說明 boolean jboolean 無符號,8 位 byte jbyte 無符號,8 位 char jchar 無符號,16 位 short jshort 有符號,16 位 int jint 有符號,32 位 long jlong 有符號,64 位 float jfloat 32 位 double jdouble 64 位 void void N/AJNI 還包含了很多對應於不同 Java 對象的引用類型如下圖:2. 如何將java傳入的String參數轉換為c的char*,然後使用?java傳入的String參數,在c文件中被jni轉換為jstring的數據類型,在c文件中聲明char* test,然後test = (char*)(*env)->GetStringUTFChars(env, jstring, NULL);注意:test使用完後,通知虛擬機平台相關代碼無需再訪問:(*env)->ReleaseStringUTFChars(env, jstring, test);3. 將c中獲取的一個char*的buffer傳遞給java?這個char*如果是一般的字元串的話,作為string傳回去就可以了。如果是含有』\0』的buffer,最好作為bytearray傳出,因為可以制定的length,如果到string,可能到』\0』就截斷了。有兩種方式傳遞得到的數據:一種是在jni中直接new一個byte數組,然後調用函數(*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer);將buffer的值到bytearray中,函數直接return bytearray就可以了。一種是return錯誤號,數據作為參數傳出,但是java的基本數據類型是傳值,對象是傳遞的引用,所以將這個需要傳出的byte數組用某個類包一下,如下:class RetObj { public byte[] bytearray; } 這個對象作為函數的參數retobj傳出,通過如下函數將retobj中的byte數組賦值便於傳出。代碼如下: jclass cls; jfieldID fid; jbyteArray bytearray; bytearray = (*env)->NewByteArray(env,len); (*env)->SetByteArrayRegion(env, bytearray, 0, len, buffer); cls = (*env)->GetObjectClass(env, retobj); fid = (*env)->GetFieldID(env, cls, "retbytes", "[B"]); (*env)->SetObjectField(env, retobj, fid, bytearray);4. 不知道佔用多少空間的buffer,如何傳遞出去呢?在jni的c文件中new出空間,傳遞出去。java的數據不初始化,指向傳遞出去的空間即可。 你還費解嗎</SPAN></SPAN></SPAN></SPAN>
</p>

㈨ linux中在java聲明了一個string在jni端怎麼調用

1.自己寫.c文件,然後生成so庫2.引用別人的靜態庫,或者動態庫來生成新的jni調用庫。我們先來看最簡單的編寫一個jni調用的so庫,包含一個獲取字元串的方法,通過這個列子,我們主要是了解怎麼在android的工程中調用jni的庫,以及要注意的問題。第一步:首先我們來看下我們的工程的目錄jni目錄是我們生成庫的文件,裡麵包含了一個.mk編譯文件以及一系列的.c文件libs目錄是我們編譯jni目錄下的mk文件動態生成的。當我們寫好了jni下面的庫文件以後,在當前目錄下執行ndk-build則會自動生成我們需要調用的.so庫文件。第二步:java裡面怎麼調用jni的庫文件,我們先看代碼{/**'hello-jni'nativelibrary,whichispackaged*withthisapplication.*/();/*thisisusedtoloadthe'hello-jni'libraryonapplication*startup.*/data/data/com.example.HelloJni/lib/libhello-jni.soat*.*/static{System.loadLibrary("hello-jni");}@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Stringstr=stringFromJNI();System.out.println("*****str:"+str);}}在java文件中要做到調用jni文件生成的so庫,需要做到2步

閱讀全文

與javajni教程相關的資料

熱點內容
grub2命令行 瀏覽:618
無法獲取加密卡信息 瀏覽:774
雲伺服器網卡充值 瀏覽:509
編程就是軟體 瀏覽:49
伺服器如何添加許可權 瀏覽:437
引用指針編程 瀏覽:851
手機加密日記本蘋果版下載 瀏覽:63
命令行括弧 瀏覽:176
java程序升級 瀏覽:490
排序演算法之插入類 瀏覽:227
gcccreate命令 瀏覽:73
海爾監控用什麼app 瀏覽:64
系統盤被壓縮開不了機 瀏覽:984
linuxredis30 瀏覽:541
狸窩pdf轉換器 瀏覽:696
ajax調用java後台 瀏覽:905
活塞式壓縮機常見故障 瀏覽:614
break演算法 瀏覽:731
換電池的app是什麼 瀏覽:771
單片機ad采樣快速發送電腦 瀏覽:22