Mac下Java JNI 调C

mac环境是:10.15.7 系统,非arm cpu。
jdk 1.8

实验一

原文来自于:Mac下Java JNI 调C

JNI的实现步骤如下:
(1)编写带有native声明的方法的Java类
(2)使用javac命令编译编写的Java类
(3)使用java -jni className 来生成后缀名为.h的头文件
(4)使用其他语言(C、C++)实现本地方法
(5)将本地方法编写的文件生成动态链接库

我们开始来编写一个简单的Java call C
1、编写含有native方法的Java类

public class HelloWorld {

    public native void hello();

    static {
        //设置查找路径为当前项目路径
        System.setProperty("java.library.path", ".");
        //加载动态库的名称
        System.loadLibrary("hello");
    }

    public static void main(String[] args) {
        new HelloWorld().hello();
    }
}

2、编译代码
在终端执行 : javac HelloWorld.java

这时会生成HelloWorld.class 文件

3、使用java -jni className 生成后缀名为.h的头文件
在终端执行 : javah HelloWorld

这时会生成HelloWorld.h 头文件. 此文件内容不能修改。看下它的内容 :

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

4、使用C语言实现本地方法
创建 HelloWorldImpl.c 文件

#include "jni.h"
#include "HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_hello(JNIEnv *env,jobject obj){
    printf("Hello World!\n");
    return;
}

5、将本地方法编写的文件生成动态链接库
使用命令生成动态链接库:

gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/include HelloWorldImpl.c -o libhello.jnilib

报错:jni_md.h文件找不到

$ gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/include Hello.c -o hello.jnilib 
In file included from Hello.c:1:
In file included from ./com_demo_TestLib_JniSo_Hello.h:2:
/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/include/jni.h:45:10: fatal error: 'jni_md.h' file not found
#include "jni_md.h"
         ^~~~~~~~~~
1 error generated.

解决办法:

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

6、last, 执行可执行文件
终端执行 : java HelloWorld

结果:

Hello World!

实验二

跨平台调用之一——java调用so库

1.编写源文件:

package com.demo.TestLib.JniSo;

public class Hello{
	static{
		System.load("/lib/libHello.so");
	}
	public native void say();
	
	public native String world(String str);
	
	public static void main(String...args){
	Hello hello = new Hello();
	hello.say();
	System.out.println("java : "+hello.world("hello"));
	}
}

2.编译Hello.java - Hello.class

javac  com/demo/TestLib/JniSo/Hello.java

3.编译Hello.class 生成 com_jni_Hello.h 的头文件

 javah com.demo.TestLib.JniSo.Hello

但是jdk9之后(大概)javah不可用了,应:
在这里插入图片描述

4.编写c++/c的业务代码,引用com_jni_Hello.h 的头文件,并实现定义的方法

#include "com_demo_TestLib_JniSo_Hello.h"
#include "string.h"
JNIEXPORT void JNICALL Java_com_demo_TestLib_JniSo_Hello_say(JNIEnv *env, jobject object){
 
        printf("hello world!");
  }

JNIEXPORT jstring JNICALL Java_com_demo_TestLib_JniSo_Hello_world(JNIEnv *env, jobject obejct, jstring string){
          const char *wd = " world!!";
          const char *getstr = (*env)->GetStringUTFChars(env,string, 0);
          char *str;

          str=strcpy(str,wd);
          str=strcpy(str,getstr); 

         jstring out= (*env)->NewStringUTF(env,str);

          return out;
  }

5.编译c/c++ 代码生成动态链接库 .jnilib文件

 gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/include Hello.c -o hello.jnilib

6.运行java程序

$ java com.demo.TestLib.JniSo.Hello       
java : hello
hello world!% 

参考网址:
1、https://www.cnblogs.com/chenmo-xpw/p/7501325.html
2、https://blog.csdn.net/weixin_38719347/article/details/103001880