JNI实践笔记

37 阅读1分钟

环境

  • MacOsX
  • jdk8
  • g++
    • Apple clang version 14.0.3

1. 编写包含 native 修饰的方法的源代码文件

touch MyClass.java

public class MyClass {

    public native String myMethod(String str);

}

2. 使用javah生成头文件

export JAVA_HOME=/usr/libexec/java_home -v 1.8.0_202

根据本机环境自行指定JAVA_HOME位置

javac MyClass.java

javah -jni MyClass

生成 MyClass.h

#include <jni.h>
/* Header for class MyClass */

#ifndef _Included_MyClass
#define _Included_MyClass
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     MyClass
 * Method:    myMethod
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_MyClass_myMethod
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

3. 根据头文件实现方法

touch MyClass.cpp

#include <jni.h>
#include <string>
#include "MyClass.h"

JNIEXPORT jstring JNICALL Java_MyClass_myMethod(JNIEnv *env, jobject obj, jstring str)
{
    const char *input = env->GetStringUTFChars(str, NULL);
    char output[256];
    strcpy(output, "Hello, ");
    strcat(output, input);
    env->ReleaseStringUTFChars(str, input);
    return env->NewStringUTF(output);
}

编译

g++ -shared -fpic -o mylib.so MyClass.cpp -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin"

因为本机系统为MacOS,所以最后引入的是$JAVA_HOME/include/darwin,可根据本机系统自行引入

此步骤生成 mylib.so 文件

4. 校验生成的动态链接库

objdump -t mylib.so

nm mylib.so

5. 使用动态链接库,并调用native方法

vi MyClass.java

public class MyClass {
    static {
        // 使用System.load加载绝对路径
        System.load("/Users/morningcat/jni-demo/mylib.so");
        // System.loadLibrary("mylib");
    }

    public native String myMethod(String str);

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        String result = obj.myMethod("world");
        System.out.println(result);
    }
}

javac MyClass.java && java MyClass