主参考文章:https://segmentfault.com/a/1190000004610577

参考上面的文章走下来,是有点问题的。下面重新整理下这篇文章的步骤:

准备阶段

  1. .java文件中创建native方法
  1. public class MacJni {
  2. public native void sayHello();
  3. static {
  4. System.loadLibrary("macjni");
  5. }
  6. public static void main(String[] args) {
  7. MacJni macJni = new MacJni();
  8. macJni.sayHello();
  9. }
  10. }
  1. javac编译.java文件,生成MacJni.class
  2. 使用javah MacJni生成MacJni.h头文件(注意javah MacJni别加后缀.class)

查看下MacJni.h内容:

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class MacJni */
  4. #ifndef _Included_MacJni
  5. #define _Included_MacJni
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10. * Class: MacJni
  11. * Method: sayHello
  12. * Signature: ()V
  13. */
  14. JNIEXPORT void JNICALL Java_MacJni_sayHello
  15. (JNIEnv *, jobject);
  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif

注意第一行#include 待会要想办法找到这个头文件

  1. 创建一个MacJni.c来实现MacJni.h头文件中定义的sayHello方法
  1. #include <stdio.h>
  2. #include "MacJni.h"
  3. JNIEXPORT void Java_MacJni_sayHello(JNIEnv * env, jobject obj){
  4. printf("hello from jni");
  5. }

引入了 MacJni.h

编译C

我们刚刚创建了MacJni.c文件,现在我们要来编译它。

按照参考文章中的命令gcc -I/System/Library/Frameworks/JavaVM.framework/Headers -c MacJni.c 是找不到’jni.h’

会报错:

MacOS Catalina Java 调用C函数 - 图1

原因是 /System/Library/Frameworks/JavaVM.framework/Headers 这个路径不正确。

在我的Mac中它的地址是/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/include

你自己该如何找到它呢?

  1. echo $JAVA_HOME 找到Java的安装目录
  2. 然后目标地址是$JAVA_HOME/include

现在使用命令gcc -I /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/include -c MacJni.c 来编译(注意,是-I 不是-L ),仍然会报错:

MacOS Catalina Java 调用C函数 - 图2

找不到jni_md.h

怎么办?

找到jni_md.h,然后把它复制到$JAVA_HOME/include目录下。那么jni_md.h在哪呢 ?

$JAVA_HOME/include/darwin目录下

所以使用命令复制一下:

sudo cp /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/include/darwin/jni_md.h /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/include

然后再使用上面的命令gcc -I /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/include -c MacJni.c就可以了。

成功后会生成一个MacJni.o文件

接着使用命令gcc -dynamiclib -o libmacjni.jnilib MacJni.o 编译生成libmacjni.jnilib

上面两条红色的命令可以合并成一条命令:gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/include MacJni.c -o libmacjni.jnilib

这里为什么是libmacjni,参考文章有提到:

static中加载native的类库macjni,注意JNI的动态库在linux上面的命名是.so文件,而在Mac OS上面的命名是.jnilib,类库的名字需要加上lib,也就是在Mac OS上面动态库的名称应该是libmacjni.jnilib

最后使用 java MacJni 就能调用本地方法了。