使用Java的JNI调用C

java的jni模块可以实现本地方法的调用,当java语言无法实现某个功能,或者效率比较低下,可以调用效率较高的c或者c++,这里以c举例。
运行环境:
jdk1.8 32位
visual studio 2013
idea
主要包括三步:

  1. 使用java编写函数声明,方法上标明native,使用javah命令生成头文件。
  2. 使用c语言实现声明的函数,同时导入jni.h,jni_md.h,和上述生成的头文件。
  3. 编写java代码,加载动态链接库,调用c。

详细过程如下:

  1. java语言编写函数声明,标明native。
package com.company.jni;

public class NativeTest {

    public static native void greeting();
}

在源文件所在目录下,执行
javac -h . NativeTest.java
生成字节码文件和头文件
如图:使用Java的JNI调用C
使用Java的JNI调用C
也可以在src目录下,执行以下命令也可以生成头文件
javah com.company.jni.NativeTest
如图:
使用Java的JNI调用C
使用visual studio创建动态链接库,注意不要使用codeblocks,这个会报错,创建过程如图:
使用Java的JNI调用C
选择DLL、空项目。
使用Java的JNI调用C
接着在项目的根目录下,添加三个头文件,直接复制即可。
- com_company_jni_NativeTest.h 第一步生成的头文件
- jni.h 在jdk/include目录下
- jni_md.h 在jdk/include/win32目录下
使用Java的JNI调用C

接着需要在解决方案资源管理器中的头文件添加现有项,添加这三个头文件。

接着在源文件添加新建项,创建test.c源文件,需要实现
com_company_jni_NativeTest.h中的函数声明。注意这个函数的名称是有讲究的。同时将这个文件的#include<jni.h> 改为#include “jni.h”。

JNIEXPORT void JNICALL Java_com_company_jni_NativeTest_greeting
  (JNIEnv *, jclass);

test.c文件

#include<stdio.h>
#include "com_company_jni_NativeTest.h"

JNIEXPORT void JNICALL Java_com_company_jni_NativeTest_greeting(JNIEnv * env, jclass cl){

    printf("hello world!");
}
  1. 编写java代码,NativeTestDemo.java
package com.company.jni;

public class NativeTestDemo {

    static{
        System.loadLibrary("native");
        // 不用加后缀名称
    }

    public static void main(String[] args) {

        NativeTest.greeting();
    }
}

注意,动态链接库在目录native/Debug下,不需要后缀名,需要在idea运行时,做如下配置,指定动态链接库的目录。
具体步骤:点击edit configurations,在vm添加如下命令行参数。

-Djava.library.path=E:\Projects\native\Debug

使用Java的JNI调用C
使用Java的JNI调用C

同时需要注意如果使用codeblocks生成的动态链接库报错如下:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.company.jni.NativeTest.greeting()V

使用jdk1.8 64位,报错如下:

E:\Projects\native\Debug\native.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

所以使用visual studio和jdk1.8 32位。

运行结果如图,调用成功。
使用Java的JNI调用C

上一篇:组合模式学习


下一篇:centos 7安装rac 11gR2时运行root.sh报错找不到ohas服务(ohasd failed to start)