需求:
工作中需要多个团队协作开发,而不同团队提供的编程语言不同,比较常见的是底层交互使用C++或c来实现任务调度,java层实现业务调度或者业务实现,正好有涉及到这方面的应用,就分享一下java使用jni调用linux中so文件的几个注意事项
编写简易的demo:
1: java代码编写jni定义的类Hello.java
package com.jni;
public class Hello{
static{
System.load("/home/admin/lib/libHello.so");
}
public native void say();
public native String world(String str);
public static void main(String...args){
Hello hello = new Hello();
hello.say();
System.out.println("java : "+hello.world("hello"));
}
}
2:编译Hello.java - Hello.class
javac -d . Hello.java
会得到 com/jni/Hello.class
3: 编译Hello.class 生成 com_jni_Hello.h 的头文件
javah com.jni.Hello
4: 编写c++/c的业务代码,引用com_jni_Hello.h 的头文件,并实现定义的方法
c代码: Hello.c
#include "com_jni_Hello.h"
#include "string.h"
JNIEXPORT void JNICALL Java_com_jni_Hello_say(JNIEnv *env, jobject object){
printf("hello world!");
}
JNIEXPORT jstring JNICALL Java_com_jni_Hello_world(JNIEnv *env, jobject obejct, jstring string){
const char *wd = " world!!";
const char *getstr = (*env)->GetStringUTFChars(env,string, 0);
char *str;
str=strcpy(str,wd);
str=strcpy(str,getstr);
jstring out= (*env)->NewStringUTF(env,str);
return out;}
c++代码:Hello.cpp
#include "com_jni_Hello.h"
#include "string.h"
JNIEXPORT void JNICALL Java_com_jni_Hello_say(JNIEnv *env, jobject object){
printf("hello world!");
}
JNIEXPORT jstring JNICALL Java_com_jni_Hello_world(JNIEnv *env, jobject obejct, jstring string){
const char *wd = " world!!";
const char *getstr = env->GetStringUTFChars(string,JNI_FALSE);
char *str;
str=strcpy(str,wd);
str=strcpy(str,getstr);
jstring out= env->NewStringUTF(str);
return out;
}
5:编译c/c++ 代码生成动态链接库 .so文件
c编译: -o
gcc -fPIC -D_REENTRANT -I/home/admin/install/jdk1.8.0_131/include -I/home/admin/install/jdk1.8.0_131/include/linux -c Hello.c
注意:第一个 -I 是jni.h 第二个是jni_md.h
-so
gcc -shared -o libHello.so Hello.o
c++:编译:
g++ Hello.cpp -fPIC -D_REENTRANT -I/home/admin/install/jdk1.8.0_131/include -I/home/admin/install/jdk1.8.0_131/include/linux -shared -o libHello.so
6:把so的路劲添加到LD_LIBRARY_PATH变量
export LD_LIBRARY_PATH=/home/admin/lib
7: 运行java程序
java com.jni.Hello
8:结果
java : hello
hello world!
------注意
1:jna是基于jni的封装,要求执行速度而言建议使用jni,但是要求开发效率而言可以直接使用jna,直接免去编译头文件和加载c/c++加载头文件这两步;
2:所有jni定义的方法都需要加入JNIEnv变量;
3:对于c++而言,新的标准库没有了.h的概念
对于c而言没有命名空间的概念