MacOS下的JNI开发

JNI (Java Native Interface,Java本地接口)是一种编程框架,使得Java虚拟机中的Java程序可以调用本地应用/或库,也可以被其他程序调用。 本地程序一般是用其它语言(C、C++或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序。
Java调用C/C++大概有这样几个步骤:

  • 编写带有native方法的Java类, 使用javac工具编译Java类
  • 使用javah来生成与native方法对应的头文件
  • 实现相应的头文件, 并编译为动态链接库(windows下是 .dll,linux下是 .so,macOS下是 .jnilib)

注意点:

  • 依赖于JNI的应用失去了Java的平台移植性(一种解决办法是为每个平台编写专门的JNI代码,然后在Java代码中,根据操作系统加载正确的JNI代码)。
  • JNI框架并没有对 non-JVM 内存提供自动垃圾回收机制,Native代码(如汇编语言)分配的内存和资源,需要其自身负责进行显式的释放。

我想用java做一些图像处理的工作,需要用到opencv,这里就以此为例.

1.编写Java类

1. 新建一个.java文件,内容如下:

package com.quickcan.watermark.util;

public class ImageProcessing {
    static {
        System.loadLibrary("image-processing");
    }

    public native void displayImage();

    public static void main(String[] args) {
        ImageProcessing imageProcessing = new ImageProcessing();
        imageProcessing.displayImage();
    }
}

2. 在ImageProcessing.java所在的目录下执行

javac ImageProcessing.java

会在当前目录下生成一个ImageProcessing.class

3. 如果ImageProcessing.java有一个package(在这里是com.quickcan.watermark.util),则需要进入这个package的根目录(在这里是com)的上级目录,执行:

javah com.quickcan.watermark.util.ImageProcessing

生成com_quickcan_watermark_util_ImageProcessing.h
内容如下:

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

#ifndef _Included_com_quickcan_watermark_util_ImageProcessing
#define _Included_com_quickcan_watermark_util_ImageProcessing
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_quickcan_watermark_util_ImageProcessing
 * Method:    displayImage
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_quickcan_watermark_util_ImageProcessing_displayImage
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

该文件定义了一个方法:Java_com_quickcan_watermark_util_ImageProcessing_displayImage,这个方法对于java文件中的native方法:public native void displayImage();.JNI在C语言中定义的规则是Java_包名_类名_方法名

2.编写C++©代码

1. 新建一个目录,用来编写.cpp(或者.c).将系统*/Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/include/darwin/* 目录下的两个文件:jawt_md.h,jni_md.h复制过来,再将上一步生成的com_quickcan_watermark_util_ImageProcessing.h也复制过来.

在当前目录下新创建一个.cpp(或者.c)文件:image-processing.cpp(这个叫什么名字无所谓),用来实现com_quickcan_watermark_util_ImageProcessing.h中的方法

//
// Created by yshhuang on 2019-06-27.
//

#include "jni.h"
#include "com_quickcan_watermark_util_ImageProcessing.h"
#include 
#include 
#include 
#include 

#include 
#include 

using namespace cv;
using namespace std;


JNIEXPORT void JNICALL Java_com_quickcan_watermark_util_ImageProcessing_displayImage
        (JNIEnv *env, jobject obj) {
    String imageName("/Volumes/develop/tool/lena.jpg");


    Mat image;
    image = imread(imageName, IMREAD_COLOR);
    if (image.empty()) {
        cout << "Could not open or find the image" << std::endl;
    }

    cout << image << endl;
    return;
};

编译这个文件:

g++ -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/include/darwin/ $(pkg-config --cflags --libs opencv4) -std=c++14 image-processing.cpp -o libimage-processing.jnilib

2. 将上一步生成的libimage-processing.jnilib放到java.library.path下面(可以通过java代码:System.out.println(System.getProperty(“java.library.path”)); 获得).

### 3. 运行第一步创建的ImageProcessing.java的main方法,即可打印出图片各点的像素值.(如果是在IntelliJ IDEA中的java项目中运行,则把libimage-processing.jnilib放到项目的根目录也可以)

你可能感兴趣的:(MacOS下的JNI开发)