Java 工具集教程

javah.exe 生成 C/C++ 头文件

javah.exe 是 Java 开发工具包(JDK)中的一个工具,用于生成 JNI(Java Native Interface)头文件。JNI 是 Java 提供的一种机制,允许 Java 代码调用本地(C/C++)代码,以便与系统级功能进行交互。

使用 javah.exe 工具可以根据 Java 类中的 native 方法生成对应的 C/C++ 头文件,这样就可以在本地代码中实现这些 native 方法。

命令格式

javah [options] <classes>

命令选项

  • -o <file>  输出文件 (只能使用 -d 或 -o 之一)

  • -d <dir>  输出目录,指定生成的头文件的输出目录。

  • -v  -verbose  启用详细输出

  • -h  --help  -?  输出此消息

  • -version  输出版本信息

  • -jni  生成 JNI 样式的标头文件 (默认值)

  • -force  始终写入输出文件,强制覆盖已存在的头文件。

  • -classpath <path>  指定 javah 工具查找类文件的路径。

  • -cp <path>  从中加载类的路径

  • -bootclasspath <path>  从中加载引导类的路径

  • <classes> 是使用其全限定名称指定的,例如:java.lang.Object

命令示例

假设您有一个名为 HelloWorld 的 Java 类,其中包含一个 native 方法 nativeMethod,您希望生成 JNI 头文件以实现该方法的本地实现。步骤如下:

(1)编写 Java 类 HelloWorld.java:

package com.hxstrive.javah;

/**
 * @author HuangXin
 * @since 1.0.0  2024/2/28 13:59
 */
public class HelloWorld {

    public native void nativeMethod();

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

}

(2)编译 Java 类:

E:\demo\src\main\java>javac ./com/hxstrive/javah/HelloWorld.java

(3)使用 javah 命令生成 JNI 头文件:

E:\demo\src\main\java>javah -jni com.hxstrive.javah.HelloWorld

执行上述命令后,将生成一个名为 HelloWorld.h 的头文件,其中包含了 nativeMethod 方法的声明。您可以在本地代码中实现该方法。如下图:

javah.exe 生成 C/C++ 头文件

com_hxstrive_javah_HelloWorld.h 文件内容如下:

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

#ifndef _Included_com_hxstrive_javah_HelloWorld
#define _Included_com_hxstrive_javah_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_hxstrive_javah_HelloWorld
 * Method:    nativeMethod
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_hxstrive_javah_HelloWorld_nativeMethod
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

(4)编写本地代码 HelloWorld.c 来实现 native 方法:

#include <stdio.h>
#include <jni.h>
#include "com_hxstrive_javah_HelloWorld.h"

JNIEXPORT void JNICALL Java_com_hxstrive_javah_HelloWorld_nativeMethod(JNIEnv *_env, jobject _obj) {
    // 在这里实现 nativeMethod 的本地代码
    printf("Hello from JNI C code!\n");
}

(5)编译本地 C 代码(注意,需要提前安装 MinGW):

E:\demo\src\main\java>gcc -shared -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" HelloWorld.c -o HelloWorld.dll

其中:

  • -I"%JAVA_HOME%\include" 和 -I"%JAVA_HOME%\include\win32" 分别指定了 JDK 的头文件路径。

  • -shared 参数表示生成共享库文件。

在编译成功后,将生成一个名为 HelloWorld.dll 动态链接库文件。

(6)将共享库加载到 Java 程序中,并调用 nativeMethod 方法。修改一下 HelloWorld.java 程序,如下:

package com.hxstrive.javah;

public class HelloWorld {

    public native void nativeMethod();

    static {
        // 加载共享库 HelloWorld.dll
        System.loadLibrary("HelloWorld");
    }

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

}

注意:运行程序前需要将 HelloWorld.dll 共享库放到 %JAVA_HOME%\bin 目录,而且还要将共享库和 JDK 版本保持一致,要么全是 32位,要么全是 64位。否则将会得到如下错误信息:

java.lang.UnsatisfiedLinkError: C:\Program Files\Java\jdk1.8.0_171\bin\HelloWorld.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
	at java.lang.ClassLoader$NativeLibrary.load(Native Method)
	at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
	at java.lang.Runtime.loadLibrary0(Runtime.java:870)
	at java.lang.System.loadLibrary(System.java:1122)
	at com.hxstrive.javah.HelloWorld.<clinit>(HelloWorld.java:12)
Exception in thread "main"
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号