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

本文详细介绍如何在JNI(Java Native Interface)环境下从C代码调用Java方法的过程。通过具体实例,包括创建Java对象、调用构造方法及成员方法等步骤,展示了整个交互流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值