美文网首页
java调用本地方法--jni访问实例域和静态域

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

作者: w1992wishes | 来源:发表于2018-05-11 16:17 被阅读82次

    本篇结构:

    • 简介
    • 实例

    一、简介

    接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 <jni.h>
    /* 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 <stdio.h>
    
    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访问实例域和静态域

          本文链接:https://www.haomeiwen.com/subject/gmnfdftx.html