Java4Android第10课_1:JNI--java调用

转载 2016年06月01日 10:59:32

Java Native Interface (JNI)是本地编程接口,它使得在 Java 虚拟机内部运行的 Java 代码能够与用其它编程语言(如 C、C++ 和汇编语言)编写的应用程序和库进行交互操作。

Native Method:使用关键字native修饰,表示该方法的实现由非java语言实现(比如C),
下面给了一个示例:    
    public class INatives
    {
      native public void Native1(String str) ;
      native static public int Native2() ;
    } 

使用本地代码的情形:
1、在该种语言中,已经有了大量测试过的和调试过的代码,且功能成熟稳定,这时候,若将这些代码移植到java语言就会显得很费时。
2、java代码通常占内存比较大,有时会降低系统性能,而像 C/C++ 它们的运行效率会高的多,当代码的执行速度至关重要的时候,可以考虑使用本地代码。
3、如果当前应用程序需要访问系统的各个特性和设备时。


Java调用c库函数的步骤:

1、java程序中使用System.loadLibrary加载c库,会导致c库中的jint JNI_OnLoad(JavaVM *jvm, void *reserved)被调用

2、在c库里面,建立java方法与c函数的映射

3、java程序中调用c库的函数

例子:

JNIDemo.java:

public class JNIDemo{
/*1. load c library*/
static{
System.loadLibrary("native");
}
public native int hello(int m);
public static void main(String args[]){
JNIDemo d = new JNIDemo();
/*3. call*/
System.out.println(d.hello(100));
}
}

native.c:

#include <jni.h>  /* /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ */
#include <stdio.h>
#if 0
typedef struct {
    char *name;          /* Java里调用的函数名 */
    char *signature;    /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */
    void *fnPtr;          /* C语言实现的本地函数 */
} JNINativeMethod;
#endif

jint c_hello(JNIEnv *env, jobject cls, jint m)
{
printf("Hello, world! val = %d\n", m);
return m+1;
}

static const JNINativeMethod methods[] = {
{"hello", "(I)I", (void *)c_hello},
};

/* System.loadLibrary */
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
JNIEnv *env;
jclass cls;
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
return JNI_ERR; /* JNI version not supported */
}
cls = (*env)->FindClass(env, "JNIDemo");
if (cls == NULL) {
return JNI_ERR;
}

/* 2. map java hello <-->c c_hello */
if ((*env)->RegisterNatives(env, cls, methods, 1) < 0)
return JNI_ERR;

return JNI_VERSION_1_4;
}

在linux下的编译方法:
javac JNIDemo.java
javah -jni JNIDemo //得到一个JNIDemo.h,里面有本地方法的定义格式和字段描述符
gcc -I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -fPIC -shared -o libnative.so native.c
export LD_LIBRARY_PATH=.
java JNIDemo


java和c库之间传递数据:

1、基本数据类型,直接使用、直接返回

2、传递字符串:

以下函数从Java中获得一个字符串,
再返回一个字符串给Java:


JNIEXPORT jstring JNICALL
Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const jbyte *str;
str = (*env)->GetStringUTFChars(env, prompt, NULL);
if (str == NULL) {
return NULL; /* OutOfMemoryError already thrown */
}
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);
/* We assume here that the user does not type more than 127 characters */
scanf("%s", buf);
return (*env)->NewStringUTF(env, buf);
}

3、传递数组

以下函数从Java中获得一个int数组,
再求和返回一个整数给Java:

JNIEXPORT jint JNICALL
Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr)
{
jint *carr;
jint i, sum = 0;
carr = (*env)->GetIntArrayElements(env, arr, NULL);
if (carr == NULL) {
return 0; /* exception occurred */
}
for (i=0; i< (*env)->GetArrayLength(env, arr); i++) {
sum += carr[i];
}
(*env)->ReleaseIntArrayElements(env, arr, carr, 0);
return sum;
}


Android HAL实现1——Java应用程序直接调用JNI库

‍ 先介绍最简单的一种实现方式 - Java应用程序直接调用JNI库。   由于JNI技术的存在,在Android中,java程序能够很好的调用C/C++库。我们这里设计一个简单的HAL,一共只...

jni4net C# java 相互调用

  • 2015年10月16日 15:13
  • 1.04MB
  • 下载

【4】在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口

在上两篇文章中,我们介绍了如何为Android系统的硬件编写驱动程序,包括如何在Linux内核空间实现内核驱动程序和在用户空间实现硬件抽象层接口。实现这两者的目的是为了向更上一层提供硬件访问接口,即为...

JNI实现C/C++与Android/JAVA相互调用

  • 2017年05月04日 20:30
  • 32.63MB
  • 下载

QtAndroid详解(4):JNI调用Android系统功能(1)

在Qt中,通过 Qt JNI 类库调用 Android 系统功能,判断网络状态,获取SDK版本,获取各种资源目录(外部存储、数据、图片、音乐、视频等),获取当前应用信息……...
  • foruok
  • foruok
  • 2015年03月01日 08:00
  • 8723

android jni c与java调用与回调的demo

  • 2013年02月26日 14:20
  • 698KB
  • 下载

Android中JNI使用详解(4)---Java与C之间数据类型转换

Jni中基本类型转换对应的表格 Java类型 本地类型 说明 boolean jboolean 无符号,8位 byte jbyte 无符号,8位 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java4Android第10课_1:JNI--java调用
举报原因:
原因补充:

(最多只允许输入30个字)