java调用本地方法--jni访问实例域和静态域

本篇结构:

  • 简介
  • 实例

一、简介

接JNI简介的基础上,新增访问实例域的例子。

  • 访问和修改实例变量操作步聚:
    调用 GetObjectClass 函数获取实例对象的 Class 引用
    调用 GetFieldID 函数获取 Class 引用中某个实例变量的 ID
    调用 GetXXXField 函数获取变量的值,需要传入实例变量所属对象和变量 ID
    调用 SetXXXField 函数修改变量的值,需要传入实例变量所属对象、变量 ID 和变量的值

  • 访问和修改静态变量操作步聚:
    调用 FindClass 函数获取类的 Class 引用
    调用 GetStaticFieldID 函数获取 Class 引用中某个静态变量 ID
    调用 GetStaticXXXField 函数获取静态变量的值,需要传入变量所属 Class 的引用和变量 ID
    调用 SetStaticXXXField 函数设置静态变量的值,需要传入变量所属 Class 的引用、变量 ID和变量的值

二、实例

2.1、编写java类

public class Employee {
    private String name;
    private double salary;

    static {
        System.loadLibrary("Employee");
    }

    public native void raiseSalary(double byPercent);

    public Employee(String n, double s){
        this.name = n;
        this.salary = s;
    }

    public void print(){
        System.out.println(name + " " + salary);
    }
}

public class EmployeeTest {
    public static void main(String[] args) {
        Employee[] staff = new Employee[3];

        staff[0] = new Employee("Tom", 35000.0);
        staff[1] = new Employee("Bob", 11000.0);
        staff[2] = new Employee("Jane", 9999.0);

        for (Employee e : staff) {
            e.raiseSalary(5);
        }

        for (Employee e : staff) {
            e.print();
        }
    }
}

2.2、编译java类

javac Employee.java

javac EmployeeTest.java

2.3、生成相关JNI方法的头文件

javah -d jnilib -jni Employee

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class Employee */

#ifndef _Included_Employee
#define _Included_Employee
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Employee
 * Method:    raiseSalary
 * Signature: (D)V
 */
JNIEXPORT void JNICALL Java_Employee_raiseSalary
  (JNIEnv *, jobject, jdouble);

#ifdef __cplusplus
}
#endif
#endif

2.4、使用C/C++实现本地方法

#include "Employee.h"
#include 

JNIEXPORT void JNICALL Java_Employee_raiseSalary(JNIEnv* env, jobject this_obj, jdouble byPercent){
    /* get the class */
    jclass class_Employee = (*env)->GetObjectClass(env, this_obj);
    
    /* get the field Id */
    jfieldID id_salary = (*env)->GetFieldID(env, class_Employee, "salary", "D");
    
    /* get the field value */
    jdouble salary = (*env)->GetDoubleField(env, this_obj, id_salary);
    
    salary *= 1 + byPercent/100;
    
    /* set the field value */
    (*env)->SetDoubleField(env, this_obj, id_salary, salary);
}

jfieldID id_salary = (*env)->GetFieldID(env, class_Employee, "salary", "D");中D代表类型double。

2.5、生成动态链接库

gcc -D_REENTRANT -fPIC -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -shared -o libEmployee.so Employee.c

2.6、运行java

最后运行。

你可能感兴趣的:(java调用本地方法--jni访问实例域和静态域)