c調用javajni
① 用java的JNI技術技術調用C++,C++運行效率會不會比單獨運行時慢
這要取決於在方法中執行的語句,如果只是作一些簡的操作,調用C/C++代碼反而會拉低效率,如果是比較復雜的一些運算如圖像處理變換等,C/C++代碼效率更高。
java中引入jni技術的原由是由於java的運行效率較低,當遇到處理圖像聲音等需要大量運算的操作時,java力不從心。所以引入執行效率較高的C/C++代碼供java調用,以彌補java的這一缺陷。
jni雖然一定程度上能夠提高效率,但要慎用,適當用。如果只作簡單的加法,卻用jni效率反而大大降低。並且jni會影響java的跨平台性和穩定性。
② 請教JNI編程中C調用Java實現中NullPointerException問題
java 與 C++ 兩種編程語言,它們之間的相互調用:
1、java 調用C++編寫的dll,可使用JNI 或 Jawin 開源項目(推薦第二種方法)。
2、C++ 調用java 的變數、方法,通過JNI (Java Native Interface)與java類交互。
----操作步驟(只總結第二個)-----
(1) vc6.0編譯C++程序,開發環境設置:工具--》選項--》工具,工具標簽下:選擇「include files」,加入頭文件目錄:C:\Program Files\Java\jdk1.5.0\include 和 C:\Program Files\Java\jdk1.5.0\include\win32 ;選擇「Libary files"下,加入LIB目錄:C:\Program Files\Java\jdk1.5.0\lib 。會編譯成exe文件。
執行程序環境設置: Path環境變數加入:C:\Program Files\Java\jdk1.5.0\jre\bin\client (jvm.dll所在目錄),若不加入path會提示,執行時找不到jvm.dll.
(2)GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
//([Ljava/lang/String;)V 是main()簽名
在java程序目錄下執行:javap -s -p ClassDemo (注:ClassDemo.java 已經編譯)
取main 下面的語句 :: Signature: ([Ljava/lang/String;)V
(3)附代碼示例:
java程序
import java.io.*;
public class DemoMain{
public static void main(String[] args) throws java.io.IOException, java.lang.NullPointerException
{
System.out.println("This is a test.");
}
}
C++程序:
#ifndef __cplusplus
#define __cplusplus
#endif
#include "jni.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma comment (lib,"C:\\Program Files\\Java\\jdk1.5.0\\lib\\jvm.lib") // 動態調用lib
#pragma warning(disable: 4129) // 關閉 warning, 4129
void main() {
LoadLibrary("C:\\Program Files\\Java\jre1.5.0\\bin\\client\\jvm.dll"); // 動態調用dll
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.classpath=.";
options[2].optionString = "-verbose:jni";
vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); // 創建虛擬機
if (res < 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
};
jclass cls = env->FindClass("DemoMain");
if (cls == 0) printf("Sorry, I can't find the class");
fprintf(stdout, "This is invokeSimplified4.\n");
jmethodID get_main_id;
if(cls != NULL)
{
get_main_id =env->GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
fprintf(stdout, "This is invokeSimplified5.\n");
if(get_main_id != NULL )
{
jclass string = env->FindClass("java/lang/String");
jobjectArray args = env->NewObjectArray(0,string, NULL);
fprintf(stdout, "This is invokeSimplified6.\n");
int i = env->CallIntMethod(cls, get_main_id, args);
fprintf(stdout, i+ "This is invokeSimplified7.\n");
}
}
jvm->DestroyJavaVM();
fprintf(stdout, "Java VM destory\n");
}
③ 怎樣用 jni來交互java與 c/c++
JNI是Java Native Interface的縮寫,中文為JAVA本地調用。使用JNI可以很方便的用我們的Java程序調用C/C++程序。很多時候,某些功能用Java無法實現,比如說涉及到底層驅動的一些功能,這時候我們就可以利用JNI來調用C或者C++程序來實現,這就是JNI的強大之處。但是JNI也有它的缺點,使用java與本地已編譯的代碼交互,通常會喪失平台可移植性。
下面是一個JNI例子,調用C++輸出"hello world":
第一步:創建Java類,在裡面定義一個本地方法(用native關鍵字修飾的方法)
public native void sayHello();
第二步:使用javah命令(javah 類的全路徑)生成本地方法的C++頭文件
在DOS窗口中進入工程所在目錄,然後執行javah com.test.TestNative命令,執行完之後就會在當前目錄生成一個後綴名為.h的頭文件,如com_test_TestNative.h,這個頭文件是根據包名和類名來命名的。
1 /* DO NOT EDIT THIS FILE - it is machine generated */
2 #include <jni.h>
3 /* Header for class com_test_TestNative */
4
5 #ifndef _Included_com_test_TestNative
6 #define _Included_com_test_TestNative
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10 /*
11 * Class: com_test_TestNative
12 * Method: sayHello
13 * Signature: ()V
14 */
15 JNIEXPORT void JNICALL Java_com_test_TestNative_sayHello
16 (JNIEnv *, jobject);
17
18 #ifdef __cplusplus
19 }
20 #endif
21 #endif
15、16行是對TestNative類中的本地方法sayHello()的聲明。這個h文件相當於我們在java裡面的介面,這里聲明了一個 Java_com_test_TestNative_sayHello (JNIEnv *, jobject);方法,然後在我們的本地方法裡面實現這個方法,也就是說我們在編寫C/C++程序的時候所使用的方法名必須和這里的一致。
第三步:編寫C/C++本地代碼,生成動態鏈接庫文件
首先在VC6.0(當然也可以用其他工具)中創建一個dll工程---Win32 Dynamic-Link Library工程。然後將上面生成的頭文件com_test_TestNative.h添加到該工程中,然後創建一個源文件引用該頭文件並且實現頭文件中本地函數的功能:
1 #include<iostream.h>
2 #include"com_test_TestNative.h"
3
4 JNIEXPORT void JNICALL Java_com_test_TestNative_sayHello(JNIEnv *env, jobject obj)
5 {
6 cout<<"hello world!"<<endl;
7 }
這里因為com_test_TestNative.h中引入了jni.h所以要將jni.h加入到VC6.0安裝目錄下的Include目錄中。jni.h在JDK安裝目錄下的include中,同時得件include/win32中的兩個頭文件jawt_md.h、jni_md.h也導入到VC6.0中。
將所依賴的頭文件導入之後,我們就可以構建該工程了,按F7就行了,完了會在工程目錄中的Degug目錄下生成一個動態鏈接庫文件,我這里生成的是NativeCode.dll。我們就可以將該dll文件拷貝到環境變數path所包含的目錄下給咱們的Java程序調用了,為了方便,我們也可以將dll所在的工程目錄加入到環境變數path中去,這樣可以避免每次都要拷貝的麻煩。注意修改環境變數之後要重啟myeclipse。
第四步:Java調用本地函數
1 package com.test;
2
3 public class TestNative {
4 public native void sayHello();
5
6 /**
7 * @param args
8 */
9 public static void main(String[] args) {
10 System.loadLibrary("NativeCode");
11 TestNative tNative = new TestNative();
12 tNative.sayHello();
13 }
14 }
第10行是載入動態鏈接庫,JVM只需要載入一次就可以調用了,「NativeCode」是上面生成的動態鏈接庫的名字,不含後綴名。
運行該程序,成功列印輸出了"hello world"。
④ 如何在c++中調用java代碼
C語言調用Java,還有Java調用C,都使用到JNI技術,C語言調用需要創建Java虛擬機,可查看函數JNI_CreateJavaVM、DestroyJavaVM的資料,函數聲明在jni.h頭文件(JDK)中。需注意參數類型轉換,兩種語言的參數類型和傳遞有講究,有多個返回的話,必須傳遞對象參數進行處理。
⑤ 如何用C語言調用JAVA的類文件
Java可以通過JNI調用本地C語言方法,而本地C語言方法是以庫文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX機器上是SO文件形式),通過調用本地的庫文件的內部方法,使Java可以實現和本地機器的緊密聯系,調用系統級的各介面方法。
⑥ android源碼里 c調java error: undefined reference to 'JNI_CreateJavaVM'求助
android 裡面的java調用c,主要是通過ndk組件來實現的,env和vm都是系統創建好了的,可以直接調用的,看的出來樓主應該是ndk方面的初學者,對jni,ndk這些東西的關系應該沒有弄清楚,如果僅僅是一個java和c互掉的話,可以看我的帖子「ndk java 和 c 互掉」:
http://jingyan..com/article/f54ae2fcde72be1e92b84916.html
帖子集文檔,截圖,視頻於一體,涉及java調用c和c調用java兩部分,
由於感覺你是ndk的初學者,所以有時間的話,建議你看看我總結的帖子"android ndk資源匯總":
http://tieba..com/p/3439627347
希望對你有用,我是ndk吧吧主,有問題可以ndk吧留言,謝謝!
⑦ jni調用 java和c是同個線程嗎
是的,jni調用時, java和c是同個線程。
檢測方法:在java和c中分別把當前線程的id輸出出來查看。
Java獲取線程Id:
Thread.currentThread().getId();
C中獲取線程Id:
GetCurrentThreadId();
⑧ Java通過JNI調用C 傳遞參數時,想傳遞地址,怎麼實現
java數組傳遞給jni實際是指針,只是java禁止你直接在jni里對java數組操作,所以在jni需要對java數組轉換為jni里可以操作的數組。典型的還有字元串,c struct等。
之所以禁止jni直接操作數組可能是jvm在安全等方面的考慮。jni調用涉及到java內存棧和native內存棧。jvm只能處理到java內存,沒有實現自動管理jni調用的內存。試想下如果jni里操作java數組剛好被回收了會怎樣?
所以在jni里需要拷貝java數組副本,而且分配或者是引用了對象,需要手動釋放刪除(DeleteLocalRef、ReleaseXX)。jni調用實際是個很大的開銷.