关于JNI的使用(实战linux平台下java调用本地c语言方法)

1 篇文章 0 订阅

1. 创建需要调用本地方法的JAVA源文件,本文以NativeTest类为例,源代码如下:

public class NativeTest {
    private native int maxNative(int a, int b);
    private native String subStringNative(String str, int begin, int end);

    static {
        System.loadLibrary("NativeTest");
    }

    public int max(int a, int b) {
        return maxNative(a, b);
    } 

    public String subString(String str, int begin, int end) {
        return subStringNative(str, begin, end);
    }

    public static void main(String[] args) {
        NativeTest test = new NativeTest();
        System.out.println("result:" + test.max(3, 8));

        String str = "Java Native Interface: Programmer's Guide and Specification";
        String subStr = test.subString(str, 0, 7);
        System.out.println(subStr);

        subStr = test.subString(str, 0, 256);
        System.out.println(subStr);

        // should throw IllegalArgumentException
        subStr = test.subString(str, -1, 7);
        System.out.println(subStr);
    }
}
这个JAVA类有两个本地方法maxNative和substringNative,在以后的C本地代码中将会实现这两个方法。

2. 编译NativeTest.java

$ javac NativeTest.java

3. 利用javah创建本地方法头文件

$ javah -jni NativeTest

生成的NativeTest.h源代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class NativeTest */

#ifndef _Included_NativeTest
#define _Included_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     NativeTest
 * Method:    maxNative
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_NativeTest_maxNative
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     NativeTest
 * Method:    subStringNative
 * Signature: (Ljava/lang/String;II)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_NativeTest_subStringNative
  (JNIEnv *, jobject, jstring, jint, jint);

#ifdef __cplusplus
}
#endif
#endif
头文件中声明了两个函数分别对应月上面JAVA类的两个本地方法.

4. 编写NativeTest.c来实现NativeTest.h的函数

#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include "NativeTest.h"

static void ThrowByName(JNIEnv *env, const char *name, const char *msg)
{
    jclass cls = (*env)->FindClass(env, name);

    if (cls != 0) /* Otherwise an exception has already been thrown */
        (*env)->ThrowNew(env, cls, msg);
}

static void ThrowNullPointerException(JNIEnv *env, const char *msg)
{
    ThrowByName(env, "java/lang/NullPointerException", msg);
}

static void ThrowIllegalArgumentException(JNIEnv *env, const char *msg)
{
    ThrowByName(env, "java/lang/IllegalArgumentException", msg);
}

static void ThrowOutOfMemoryError(JNIEnv *env, const char *msg)
{
    ThrowByName(env, "java/lang/OutOfMemoryError", msg);
}

JNIEXPORT jint JNICALL
Java_NativeTest_maxNative(JNIEnv *env, jobject obj, jint a, jint b)
{
    return (a > b ? a : b);
}

JNIEXPORT jstring JNICALL
Java_NativeTest_subStringNative(JNIEnv *env, jobject this, jstring str, jint begin, jint end)
{
    const jbyte *s;
    char *sub;

    int total_len, sub_len;

    s = (*env)->GetStringUTFChars(env, str, NULL);
    if (s == NULL) {
        return NULL; /* OutOfMemoryError already thrown */
    }

    total_len = strlen(s);
    if (begin < 0 || begin >= total_len || begin > end) {
        (*env)->ReleaseStringUTFChars(env, str, s);
        ThrowIllegalArgumentException(env, "Invalid arguments");
        return NULL;
    }

    sub_len = (end >= total_len) ? (total_len-begin) : (end-begin+1);
    sub = (char *)malloc(sizeof(char)*(sub_len+1));
    if (sub == NULL) {
        (*env)->ReleaseStringUTFChars(env, str, s); 
        ThrowOutOfMemoryError(env, "Can not allocate memory.");
        return NULL;
    }

    strncpy(sub, s+begin, sub_len);   
    jstring jsub = (*env)->NewStringUTF(env, sub); 

    (*env)->ReleaseStringUTFChars(env, str, s);
    free(sub);
    return jsub;
}

5. 编译C源文件并生成动态链接库

$ gcc -fPIC -c -I/usr/local/tools/jdk1.6.0_25/include -I/usr/local/tools/jdk1.6.0_25/include/linux NativeTest.c

$ gcc -shared -o libNativeTest.so NativeTest.o

6. 设置java.library.path运行java程序

$ java -Djava.library.path=. NativeTest

运行结果如下:

result:8
Java Nat
Java Native Interface: Programmer's Guide and Specification
Exception in thread "main" java.lang.IllegalArgumentException: Invalid arguments
        at NativeTest.subStringNative(Native Method)
        at NativeTest.subString(NativeTest.java:14)
        at NativeTest.main(NativeTest.java:29)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值