javah 已被 OpenJDK 10+ 彻底移除,唯一官方替代方案是 javac -h,需在编译时指定输出目录生成 JNI 头文件,且必须确保类已声明 public native 方法并正确编译。

javah 已被移除,OpenJDK 10+ 不再支持
从 OpenJDK 10 开始,javah 工具已被彻底移除。如果你用的是 OpenJDK 11/17/21/25 等主流 LTS 版本,直接运行 javah -jni MyClass 会报错:Command 'javah' not found。这不是环境变量没配好,而是它真的没了。
替代方案:用 javac -h 生成 JNI 头文件
OpenJDK 8 起就提供了替代方式,10+ 版本唯一官方支持的方法是:javac -h。它会在指定目录下生成标准的 *.h 文件,内容与旧版 javah 完全一致。
- 确保你的 Java 类已声明
public native方法,并已编译为.class文件(如HelloJNI.class) - 执行命令:
javac -h ./jni_include HelloJNI.java(./jni_include是输出目录,会自动创建) - 生成的头文件名是
com_example_HelloJNI.h(若类在com.example包下),函数签名格式仍为JNIEXPORT void JNICALL Java_com_example_HelloJNI_sayHello(JNIEnv*, jobject) - 注意:
-h参数必须在javac编译时使用;如果已存在.class文件但没带-h,需重新编译,不能补救
常见错误和路径陷阱
即使命令写对,也容易因路径或权限失败:
-
error: cannot find symbol:说明HelloJNI.java里引用了其他未编译的类,或包声明与目录结构不匹配(如声明package com.example;,但文件不在com/example/HelloJNI.java路径下) - 输出目录不可写(尤其在
/usr或系统路径下):改用当前用户有写权限的路径,比如./jni_out - 头文件中缺失
#include <jni.h></jni.h>路径:javac -h不负责设置 include 路径,后续用gcc编译 C 文件时才需要显式加-I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux - Windows 下路径含空格(如
C:\Program Files\Java\...):会导致gcc找不到jni.h,建议将 JDK 安装到无空格路径(如C:\jdk-21),并设JAVA_HOME=C:\jdk-21
为什么不用 javah,也不推荐用第三方脚本模拟
有人试图用 javap -s + 手动拼接函数名来“复刻” javah,这非常危险:
- 函数名拼接规则复杂(涉及内部类、泛型擦除、数组维度符号
[Lxxx;),稍错一个字符就会导致UnsatisfiedLinkError - 无法自动生成正确的宏保护(
#ifndef _Included_XXX)、extern "C"块、以及__cplusplus条件编译 - OpenJDK 的 JNI 函数签名规范在不同版本间有细微调整(如对
staticnative 方法的处理),javac -h始终与当前 JDK 严格同步
真正省事又可靠的方式,就是老老实实用 javac -h —— 它不是备选,是唯一正解。别绕路,绕了反而卡在 java.lang.UnsatisfiedLinkError: no xxx in java.library.path 里出不来。


















