JNI学习之java 调用C/C++本地库

JNI

什么是JNI?

Java Native Interface
Java本地接口

JNI能做什么?

开发JNI程序会受到系统环境的限制,因为用C/C++语言写出来的代码或模块,编译过程当中要依赖当前操作系统环境所提供的一些库函数,并和本地库链接在一起。而且编译后生成的二进制代码只能在本地操作系统环境下运行,因为不同的操作系统环境,有自己的本地库和CPU指令集,而且各个平台对标准C/C++的规范和标准库函数实现方式也有所区别。这就造成使用了JNI接口的JAVA程序,不再像以前那样自由的跨平台。如果要实现跨平台,就必须将本地代码在不同的操作系统平台下编译出相应的动态库。


Demo流程(OS X下)

一 编写声明了native关键字的java类,保存于HelloWorld.java

  1. 在本地创建一个文件夹jnitest
  2. jnitest文件夹下创建HelloWorld.java;
  3. HelloWorld.java代码如下:
package com.study.jnilearn;

public class HelloWorld{
    public static native String sayHello(String name);
    public static void main(String[] args){
        System.loadLibrary("HelloWorld");
        String text = sayHello("HelloWorld!");
        System.out.println(text);
    }
}

二 使用javac将HelloWorld.java源代码编译成HelloWorld.class字节码文件

1.在jnitest下创建一个bin文件夹
2.使用 javacHelloWorld.java 源代码编译成 HelloWorld.class 字节码文件

javac HelloWorld.java -d bin

3.这样会在bin文件夹下生成对于的class文件,其路径为bin/com/study/jnilearn/HelloWorld.class


三 将使用javah生成对应的头文件HelloWorld.h

javah -jni -classpath bin -o HelloWorld.h com.study.jnilearn.HelloWorld

这会在jnitest文件夹下生成HelloWorld.h文件


四 创建HelloWorld.c文件,并实现里面的native方法

在HelloWorld.h的同级目录下新建一个HelloWorld.c文件,实现native声明的方法

#include "HelloWorld.h"

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_study_jnilearn_HelloWorld
 * Method:    sayHello
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello
  (JNIEnv *env, jclass cls, jstring j_str){
        const char *c_str = NULL;
        char buff[128] = {0};
        c_str = (*env)->GetStringUTFChars(env, j_str, NULL);
        if (c_str == NULL){
            printf("out of memory.\n");
            return NULL;
        }
        (*env)->ReleaseStringUTFChars(env, j_str, c_str);
        printf("C Str:%s\n", c_str);
        sprintf(buff, "%s", c_str);
        return (*env)->NewStringUTF(env, buff);
  }

#ifdef __cplusplus
}
#endif

五 编译C代码,生成本地库

gcc -dynamiclib -o libHelloWorld.jnilib HelloWorld.c -framework JavaVM -I$JAVA_HOME/include -I/$JAVA_HOME/include/darwin

这样会在jnitest文件夹下生成libHelloWorld.jnilib


六 运行java程序

java -classpath bin com.study.jnilearn.HelloWorld

输出:

C Str:HelloWorld!
HelloWorld!

c++代码生成动态库的不同之处

1.新建cpp文件,对于JNIEnv *env的调用是不同的

#include "HelloWorld.h"

extern "C" {
/*
 * Class:     com_study_jnilearn_HelloWorld
 * Method:    sayHello
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_study_jnilearn_HelloWorld_sayHello
  (JNIEnv *env, jclass cls, jstring j_str){
        const char *c_str = NULL;
        char buff[128] = {0};
        c_str = env->GetStringUTFChars( j_str, NULL);
        if (c_str == NULL){
            printf("out of memory.\n");
            return NULL;
        }
        env->ReleaseStringUTFChars(j_str, c_str);
        printf("C Str:%s\n", c_str);
        sprintf(buff, "%s", c_str);
        return env->NewStringUTF(buff);
  }
}

2.生成动态库的源文件是不同的

gcc -dynamiclib -o libHelloWorld.jnilib HelloWorld.cpp -framework JavaVM -I$JAVA_HOME/include -I/$JAVA_HOME/include/darwin
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值