美文网首页
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访问实例域和静态域

    本篇结构: 简介 实例 一、简介 接JNI简介的基础上,新增访问实例域的例子。 访问和修改实例变量操作步聚:调用 ...

  • Java中的变量

    一、Java中定义的变量类型: 实例变量(非静态域):不用static关键字修饰域的域,即非静态域(Non-Sta...

  • JNI 实现与原生代码通信

    目录 1.JNI 字符串操作 2.JNI 数组 3.NIO 操作 4.访问域,获得成员函数,与调用方法。 5.异常...

  • C/C++ 访问 Java 实例变量和静态变量

    实例变量和静态变量在上一章中我们学习到了如何在本地代码中访问任意 Java 类中的静态方法和实例方法,本章我们也通...

  • java并发编程的艺术 -- java内存模型

    java内存模型的抽象结构 实例域、静态域、数组元素存储在堆内存,堆内存是线程间共享的局部变量、方法定义参数、异常...

  • Effective Java 第4条:通过私有构造器强化不可实例

    类似 java.lang.Math 和 java.util.Arrays 等类, 只包含静态方法和静态域. 这些...

  • 类加载和初始化

    对象的创建过程 当首次创建某个类的对象时(构造器可看作静态方法),或者类的静态方法/静态域被访问时,Java解释器...

  • JNI

    JNI: Java Native Interface ;Java本地调用 JNI功能: 可以实现Java函数和Na...

  • 2019-06-26

    JavaScript静态作用域和动态作用域实例详解 静态作用域:一段代码,在它执行之前就已经确定了它的作用域,简单...

  • 四、MagicCamera3#C++与Kotlin之间的衔接

    NDK和JNI JNI是Java Native Interface(JAVA本地接口)的缩写,为了方便Java调用...

网友评论

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

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