Java可执行命令详解之javah

1️⃣ 概念
javah 是一个命令行工具,旨在为开发人员提供一种将 Java 类转换为 C/C++ 头文件的方式。它最初作为 Java SE 开发套件的一部分于 JDK 1.0 版本中引入,旨在支持 Java 和本地代码的混合编程。
javah 用于生成包含 JNI(Java Native Interface)函数原型的头文件,以便在使用 JNI 连接 Java 和本地代码时进行编译和链接。
它的主要作用是为了在 Java 和 C/C++ 之间建立桥梁,允许 Java 程序调用本地代码功能,并使本地代码能够与 Java 类进行交互。通过生成头文件,开发人员可以将 Java 类的方法映射到本地函数,并为这些函数构建对应的本地实现。
 
2️⃣ 优势和缺点
-  优点: - 方便地将 Java 类连接到本地代码,充分利用底层操作系统的功能;
- 支持编写高性能的本地代码,以提高某些关键任务的执行效率;
- 加强了跨平台开发的能力,可以充分利用本地特性,实现更复杂的功能需求。
 
-  缺点: - 使用 JNI 需要额外的学习成本,包括 JNI 编程规范、内存管理等方面的知识;
- 开发人员需要维护 Java 类和本地代码之间的正确映射关系,增加了一定的复杂性。
 
 
3️⃣ 使用
3.1 语法格式
javah 命令的基本语法格式如下:
javah [options] <classes>
其中,options 是可选参数,classes 是要生成头文件的完全限定类名。
将 javah 命令支持的所有可选参数汇总如下表:
| 参数 | 作用 | 
|---|---|
| -o <file> | 输出文件 (只能使用 -d 或 -o 之一) | 
| -d <dir> | 输出目录 | 
| -v或-verbose | 启用详细输出 | 
| -h或--help或-? | 输出此消息 | 
| -version | 输出版本信息 | 
| -jni | 生成 JNI 样式的标头文件 (默认值) | 
| -force | 始终写入输出文件 | 
| -classpath <path> | 从中加载类的路径 | 
| -cp <path> | 从中加载类的路径 | 
| -bootclasspath <path> | 从中加载引导类的路径 | 
上面表格汇总了javah的所有可选参数,读者可以根据自己的需求参照表格选择所需参数。下是主要介绍一些常用的 javah可选参数:
- -o <file>:指定输出的头文件名称;
- -classpath <path>:设置查找类文件的路径;
- -jni:表示生成用于 JNI 的头文件。
 
3.1.1 可选参数:-o < file>
javah -o <file> classes 命令的作用是生成包含 JNI 函数原型的 C/C++ 头文件,并将其写入指定的文件中。
其中,<file> 是指定要写入的文件的路径和名称,classes也即fully.qualified.classname 是要生成头文件的完全限定类名。
以下步骤演示了如何使用该命令及其作用:
-  使用以下命令,将一个名为 com.xiaoshan.MyClass的 Java 类生成头文件并保存为MyClass.h:javah -o MyClass.h com.xiaoshan.MyClass执行命令后,会在当前目录下生成一个名为 MyClass.h的头文件,其中包含与com.xiaoshan.MyClass类相关的 JNI 函数原型。
-  生成的头文件可以用于编写本地代码,实现与 Java 类的交互。你可以通过包含该头文件来在 C/C++ 代码中调用 Java 类的方法或访问其成员。 
使用 javah -o <file> 命令可以方便地为 Java 类生成与 JNI 接口对应的 C/C++ 头文件。C/C++ 头文件内容为:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xiaoshan_MyClass */
#ifndef _Included_com_xiaoshan_MyClass
#define _Included_com_xiaoshan_MyClass
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
3.1.2 可选参数:-classpath < path>
javah -classpath <path> classes 命令的作用是设置要在查找类文件时使用的路径。
其中,<path> 是指定要使用的类文件路径,可以是一个目录或包含多个目录路径的冒号分隔列表。classes 是要生成头文件的完全限定类名。
下面演示如何使用该命令及其作用:
-  现在有一个 com.xiaoshan.MyClass的 Java 类,并且该类所在的类文件位于/path/to/classes目录下,则可以执行以下命令:javah -classpath /path/to/classes com.xiaoshan.MyClass执行命令后, javah将根据-classpath参数指定的路径在其中查找类文件,并为com.xiaoshan.MyClass生成相应的 C/C++ 头文件。
-  运行命令后, javah将会根据指定的类路径查找类文件,并生成相应的头文件。生成的头文件可以用于编写本地代码,实现与 Java 类的交互。
使用 javah -classpath <path> 命令可以设置要在查找类文件时使用的路径,确保 javah 能够正确地找到要生成头文件的 Java 类。
 
3.1.3 可选参数:-jni
javah -jni 命令的作用是生成用于 JNI(Java Native Interface)的头文件。这意味着生成的头文件会符合 JNI 的函数命名规则,以便与 Java 代码进行交互。
下面演示如何使用该命令及其作用:
-  现在希望名为 com.xiaoshan.MyClass的 Java 类生成的头文件符合 JNI 的命名规范,可以执行以下命令:javah -jni com.xiaoshan.MyClass运行命令后, javah将会生成一个符合 JNI 命名规范的头文件,其中包含与com.xiaoshan.MyClass类相关的 JNI 函数原型。
-  生成的头文件可以用于编写本地代码,实现与 Java 类的交互。通过 JNI 的函数命名规则,你可以在 C/C++ 代码中调用 Java 类的方法或访问其成员。 
使用 javah -jni 命令可以方便地生成用于 JNI 的头文件,并确保与 Java 代码的交互遵循 JNI 函数命名规则。这样,你就能够在本地代码中正确调用 Java 类的方法并与之进行交互。
 
4️⃣ 应用场景
javah 命令主要在以下场景中发挥作用:
- 在 Java 程序中使用 JNI 连接本地代码时,需要生成对应的 C/C++ 头文件;
- 需要优化 Java 程序的性能,将部分关键任务委托给本地代码实现。
 
5️⃣ 实现原理
javah 命令通过分析 Java 类及其方法的签名信息,生成与之对应的 C/C++ 函数原型。具体过程如下:
- 根据指定的类名或包名,javah定位到相应的类文件;
- 解析类文件的结构,提取类和方法的相关信息,包括类名、方法名、参数列表和返回类型等;
- 将提取的信息转换为 C/C++ 函数原型,并生成相应的头文件;
- 头文件中包含了 JNI 的函数命名规则,以便与 Java 代码进行交互。
 
6️⃣ 注意事项
- javah只能应用于具有- native关键字声明的方法,用于标识应该由本地代码提供实现;
- 如果涉及到依赖其他类的本地方法,需确保这些类在运行时可用;
- 在执行 javah命令时,必须指定一个有效的输出路径。
 
🌾 总结
javah 是一个有用的工具,可以方便地将 Java 类连接到 C/C++ 代码中。它允许开发人员通过生成 JNI 头文件来建立 Java 和本地代码之间的桥梁,实现高效的跨平台开发。尽管涉及一定的学习成本和复杂性,但对于需要与底层操作系统交互或提高性能的情况下,使用 javah 是一个很好的选择。
 











