ubuntu下Java通过JNI调用C

下面看一个实例,如下:

public class TestJNI {
	static {
		System.loadLibrary("diaoyong"); // 程序在加载时,自动加载libdiaoyong.so库
	}

	public native void set(int value); // 声明原生函数。注意要添加native关键字

	public native int get();

	public static void main(String[] args) {
		TestJNI test = new TestJNI();
		test.set(1);
		System.out.println(test.get());
	}
}

javac  TestJNI.java命令生成java.class文件

javah -jni TestJNI命令生成TestJNI.h文件,内容如下:

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

#ifndef _Included_TestJNI
#define _Included_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     TestJNI
 * Method:    set
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_TestJNI_set
  (JNIEnv *, jobject, jint);

/*
 * Class:     TestJNI
 * Method:    get
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_TestJNI_get
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。

jint是以JNI为中介使Java的int类型与本地的int沟通的一种类型。

Java C/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

对于数组型参数,

Java C/C++
boolean[ ] JbooleanArray
byte[ ] JbyteArray
char[ ] JcharArray
short[ ] JshortArray
int[ ] JintArray
long[ ] JlongArray
float[ ] JfloatArray
double[ ] JdoubleArray

函数的名称是Java_+Java程序的package路径+函数名组成的。

Dynamic linkers resolve entries based on their names. A native method name is concatenated from the following components:

扫描二维码关注公众号,回复: 6996422 查看本文章
  • the prefix Java_
  • a mangled fully-qualified class name
  • an underscore (“_”) separator
  • a mangled method name
  • for overloaded native methods, two underscores (“__”) followed by the mangled argument signature

对于本地方法参数来说

函数的名称是Java_+Java程序的package路径+函数名组成的。

 

第一个参数JNIEnv接口指针,指向一个个函数表,函数表中的每一个入口指向一个JNI函数。本地方法经常通过这些函数来访问JVM中的数据结构。下图演示了JNIEnv这个指针:

第二个参数根据本地方法是一个静态方法还是实例方法而有所不同。本地方法是一个静态方法时,第二个参数代表本地方法所在的类;本地方法是一个实例方法时,第二个参数代表本地方法所在的对象。如上例子当Java_TestJNI_get与Java_TestJNI_set是一个实例方法,因此jobject参数指向方法所在的对象。

 

继续编写对应的c语言的实现,如下:

#include <stdio.h> 

#include "TestJNI.h" 

int i=0; 

JNIEXPORT void JNICALL Java_TestJNI_set (JNIEnv * env, jobject obj, jint j) { 
   i=j*888; 
}


JNIEXPORT jint JNICALL Java_TestJNI_get (JNIEnv * env, jobject obj){
  printf("ok!You have successfully passed the Java call c\n");
  return i; 
}  

gcc -Wall -fPIC -c TestJNI.c -I ./ -I /home/mazhi/workspace/jdk1.8.0_192/include/linux/ -I /home/mazhi/workspace/jdk1.8.0_192/include/ 命令生成TestJNI.o文件。

命令中-Wall:打开警告开关。-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。

编译~/.bashrc文件,添加环境变量的配置export LD_LIBRARY_PATH=./ 使用source ~/.bashrc命令使配置生效

java TestJNI对文件进行运行即可。

 

参考文章:

https://jingyan.baidu.com/album/6c67b1d68e33bc2787bb1ee6.html?picindex=3

猜你喜欢

转载自www.cnblogs.com/mazhimazhi/p/11330528.html
今日推荐