JNI(在Java中调用C函数)

Author Avatar
罗炜光 9月 26, 2016
  • 在其它设备中阅读本文章

JNI调用C函数的步骤

  • 编写Java代码
  • 编译Java代码
  • 生成C语言头文件
  • 编写C代码
  • 生成C共享库
  • 运行Java程序

编写Java代码

package com.jni;

public class HelloJNI {

    //本地方法声明
    native void printHello();
    native void printString(String str);

    //加载库
    static { System.loadLibrary("hellojni"); }

    public static void main(String[] args) 
    {
        HelloJNI myJNI = new HelloJNI();

        //调用本地方法(实际调用的是使用C语言编写的JNI本地函数)
        myJNI.printHello();
        myJNI.printString("Hello World from printString fun");
    }
}

在Java类中,使用“native”关键字,声明本地方法,该方法与用C/C++编写的JNI本地函数相对应。

“native”关键字告知Java编译器,在Java代码中带有该关键字的方法只是声明,具体由C/C++等其他语言编写实现

在Java中加载本地运行库时通常使用“静态块”。如果本地库未被正常加载,在使用本地方法调用本地库的C函数时,就会发生错误

编译Java代码

javac <文件路径>

例如:

javac HelloJNI.java

生成C语言头文件

javah <包含以native关键字声明的方法的Java类名称>

例如:

javah HelloJNI

HelloJNI.h

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

#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloJNI
 * Method:    printHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloJNI_printHello
  (JNIEnv *, jobject);

/*
 * Class:     HelloJNI
 * Method:    printString
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_HelloJNI_printString
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

编写C代码

c文件中对应的方法名为生成的C语言头文件中对应的函数原型
hellojni.c

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

JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *env, jobject obj)
{
    printf("Hello World!\n");
    return;
}

JNIEXPORT void JNICALL Java_HelloJNI_printString(JNIEnv *env, jobject obj, jstring string)
{
    //GetStringUTFChars()是JNI函数,用来将Java字符串转成C语言字符串
    const char *str = (*env)->GetStringUTFChars(env,string,0);
    printf("%s\n", str);
    return;
}

生成C共享库

gcc -shared -o <库的路径> <c文件路径>
gcc -shared -o hellojni.dll hellojni.c

注意事项

  • In file included from hellojni.c:1:com_jni_HelloJNI.h:2:17: jni.h: No such file or directory
    复制JDK目录以下的这三个文件至编译器的include文件夹下

    • jdk\include\jni.h
    • jdk\include\win32\jawt_md.h
    • jdk\include\win32\jni_md.h
  • Exception in thread “main” java.lang.UnsatisfiedLinkError: H:\hellojni.dll: Can’t load IA 32-bit .dll on a AMD 64-bit platform
    编译的版本应该与系统版本一致,64位的应使用64位的编译

运行Java程序

java <类名>
java HelloJNI

运行结果

Hello World!
Hello World from printString fun

参考资料

Amdroid框架揭秘