Java可执行命令详解之javah
- 1️⃣ 概念
- 2️⃣ 优势和缺点
- 3️⃣ 使用
- 3.1 语法格式
- 3.1.1 可选参数:-o < file>
- 3.1.2 可选参数:-classpath < path>
- 3.1.3 可选参数:-jni
- 4️⃣ 应用场景
- 5️⃣ 实现原理
- 6️⃣ 注意事项
- 🌾 总结
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
是一个很好的选择。