Jni笔记

参考书籍《Java核心技术 卷II》。

本文仅提供jni的语法,不包含具体编译器的操作。

在Android Studio 2.3中使用jni的教程:http://mp.weixin.qq.com/s/5DHJa5E-lZzy21-9edxoIg

使用目的

  虽然使用Java开发Android程序相对于用C有着各种各样的优势,但是Java也有一些不知的地方,比如能被轻松地反编译,所以在进行一些比较隐私的操作时,C是一个更好的选择。另外使用C也能提高不少程序的效率,进行一些底层的操作也比较方便。

简单使用

在Java类中放置一个使用native关键字表示的本地方法,如下:

1
2
3
4
5
6
pulic class HelloJni {
/**
*类似于抽象方法不提供方法的具体实现
*/
public static native String hello();
}

为实现这个方法需建立一个与之对应的C语言函数。为了与之对应,必须使用完整Java方法名,例如:com.jay86.HelloJni,hello,然后将.替换为_并加上Java_前缀,例如:Java_com_jay86_HelloJni_hello。完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_jay86_HelloJni_hello(
JNIEnv* env /*调用jni函数需要用到的东西,下面会看到*/,
jclass cl /*非静态时是jobject相当于this,静态时是jclass相当于Class*/) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

最后在HelloJni类中加载它:

1
2
3
4
5
6
7
8
9
10
11
pulic class HelloJni {
static {
/*native-lib是C\C++的文件名*/
System.loadLibrary("native-lib");
}

/**
*类似于抽象方法不提供方法的具体实现
*/
public static native String hello();
}

这样,一个jni程序就完成了。但是jni程序还有更多需要学习的。

参数传递与返回值

Java数据类型与C语言数据类型对应关系

Java C 字节
boolean jboolean 1
byte jbyte 1
char jchar 2
short jshort 2
int jint 4
long jlong 8
float jfloat 4
double jdouble 8

实现简单参数传递

ps:方便起见,直接在之前的代码中添加了两个参数,并没有对其做任何操作。

  • Java中

    1
    2
    3
    4
    5
    6
    pulic class HelloJni {
    static {
    System.loadLibrary("native-lib");
    }
    public static native String hello(int a, double b);
    }
  • C中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <jni.h>
    #include <string>

    extern "C" /*C++需要添加上这一句,不太清楚原因*/
    JNIEXPORT jstring JNICALL
    Java_com_jay86_HelloJni_hello(
    JNIEnv* env,
    jclass cl, jint a, jdouble b) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
    }

字符串参数

由于C语言和Java语言的字符串存在一系列的不同,传递字符串时需要进行一些处理:

  • jstring -> char*

    1
    2
    3
    4
    jString jstr = "hello world";
    char* cstr = (*env)->GetStringUTFChars(env, jstr, NULL);
    //不再访问时释放
    (*env)->ReleaseStringUtf(env, format, cformat);
  • char* -> jstring

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //C
    char cstr[] = "hello world";
    jstring jstr;
    jstr = (*env)->NewStringUTF(env, cstr);

    //C++
    std::string hello = "Hello from C++";
    jstring jstr;
    jstr = env->NewStringUTF(hello.c_str());

访问域