您的位置:首页 > 运维架构 > Linux

java开发第二个jni示例程序(基于linux操作系统)--native层调用java方法

2016-10-10 20:38 806 查看
java开发第一个jni示例程序(基于linux操作系统)--java层调用native方法一文中向大家介绍了java层如何调用native层的方法,建议大家先读那一篇博客,因为编程的思路没变,重复的我就没写,只写了区别,写文章比变成累多了,这篇文章中我将向大家介绍如何在native层调用java层的方法。

基本步骤依然是:

1、新建java文件(JniMain.java,JniTest.java)

2、编译java文件(JniMain.class,JniTest.class)

3、生成c的头文件(JniMain.h)

4、新建c文件(JniNative.c)

5、生成动态链接库(JniNative.so)

6、运行java程序

有了之前的基础,在这里,native调用java层的方法主要在JniNative.c文件中,其他文件基本没变,大家自行查看,我对JniNative.c进行了详细注释,我直接上代码:

JniMain.java
public class JniMain{
static{
System.load("/home/zhangmingbao/user/java/jnitest1/JniNative.so");
}
private static int staticIntField = 300;
private static native JniTest oncrateobjForJniTest();
public static void main(String[] args) {
System.out.println("oncrateobjForJniTest() call native method");
JniTest jniTest = oncrateobjForJniTest();
jniTest.callTest();
}
}


JniTest.java
public class JniTest{
private int intField;
public JniTest(int num)
{
intField = num;
System.out.println("use JniTest constructure:"+intField);
}
public void callByNative(int num)
{
System.out.println("JniTest.callByNative function was called:"+num);
}
public void callTest()
{
System.out.println("obj of JniTest is called , intField = "+intField);
}
}


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

#ifndef _Included_JniMain
#define _Included_JniMain
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     JniMain
* Method:    oncrateobjForJniTest
* Signature: ()LJniTest;
*/
JNIEXPORT jobject JNICALL Java_JniMain_oncrateobjForJniTest
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif


JniNative.c
#include "JniMain.h"
#include <stdio.h>
/*此本地方法在java类中申明是静态的,静态的类可以通过类名直接调用,所以传递的第二个参数是jclass,是指的对类的引用,而在前一篇写jni的博客中因为没有把方法申明为静态的,所以传递的是jobject,即对象的引用*/
JNIEXPORT jobject JNICALL Java_JniMain_oncrateobjForJniTest
(JNIEnv *env, jclass clazz)
{
/*申明一个jclass类类型变量*/
jclass targetClass;
/*申明一个jint类型变量(对应java中的int)*/
jint staticIntField;
/*申明一个jmethodID类型变量,保存方法的ID*/
jmethodID mid;
/*申明一个jfieldID类型变量,保存变量的ID*/
jfieldID fid;
/*申明一个jstring类型变量,对应java的String*/
jstring res;
/*申明一个jobject类型变量,对应较多,请查看c与java变量类型的对应关系*/
jobject obj;
/*获取JniMain.java中的staticIntField变量的ID,clazz是传入的参数,是对JniMain.java的引用,"I"是变量的描述符。代表这是一个int类型的变量,变量描述符或者方法描述符可以通过反编译javap -s -p JniTest查看*/
fid = (*env)->GetStaticFieldID(env,clazz,"staticIntField","I");
/*获取JniMain.java中的staticIntField变量的值,clazz是传入的参数,是对JniMain.java的引用。*/
staticIntField = (*env)->GetStaticIntField(env,clazz,fid);
printf("staticIntField =%d\n", staticIntField);
printf("%s\n", "12334344444444444");
/*查找JniTest.java类,添加targetClass对JniTest.java的引用*/
targetClass = (*env)->FindClass(env,"JniTest");
/*获取JniTest.java类的构造方法的ID,"<init>"代表构造方法,"(I)V"代表方法描述符,I代表参数为int类型,V代表函数返回值为void*/
mid = (*env)->GetMethodID(env,targetClass,"<init>","(I)V");
/*创建对象,100是构造方法中的参数*/
obj = (*env)->NewObject(env,targetClass,mid,100);
/*获取JniTest.java中的callByNative方法*/
mid = (*env)->GetMethodID(env,targetClass,"callByNative","(I)V");
/*调用JniTest.java类的callByNative方法,200是参数*/
(*env)->CallVoidMethod(env,obj,mid,200);
fid =
/*查找JniTest.java类中intField的ID*/     (*env)->GetFieldID(env,targetClass,"intField","I");
/*为JniTest.java类中intField变量赋值*/
(*env)->SetIntField(env,obj,fid,200);
/*返回一个JniTest.java对象*/
return obj;
}


Makefile

JniNative.so:JniNative.o
gcc -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" -shared -o JniNative.so JniNative.o
JniNative.o:JniNative.c
gcc -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" -c -fPIC -o JniNative.o JniNative.c
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java native jni linux