核心原理:Java 与 COM 的桥梁
想象一下,Java 运行在 Java 虚拟机中,是一个“外国人”,而 ActiveX 控件是基于 Windows 的 COM (Component Object Model) 技术,是“本地人”,Java 无法直接和“本地人”沟通。

我们需要一个“翻译官”或“中间人”,这个“中间人”JNI (Java Native Interface) 和 特定的库,这些库能够:
- 在 Java 和 Windows 之间建立一座桥。
- 让 Java 能够创建、调用和操作 COM 对象(也就是你的 ActiveX 控件)。
- 处理数据类型之间的转换(Java 类型 ↔ COM/VB 类型)。
最主流和推荐的“桥梁”库是 Jacob (Java-COM Bridge)。
推荐工具:Jacob (Java-COM Bridge)
Jacob 是一个开源的 Java 库,它使用 JNI 来提供对 Windows COM 组件的访问,它轻量级、易用,并且社区活跃,是解决 Java 调用 ActiveX 问题的首选方案。
优点:

- 简单易用:API 设计直观,学习成本低。
- 轻量级:不需要庞大的 JRE 或复杂的配置。
- 开源免费:可以自由使用和修改。
详细步骤:使用 Jacob 调用 ActiveX 控件
假设我们要调用一个常见的 ActiveX 控件:Microsoft Web Browser (Shdocvw.dll),用来在 Java 程序中嵌入一个 IE 内核的浏览器窗口。
第 1 步:准备工作
-
下载 Jacob
- 访问 Jacob 的官方发布页面:https://github.com/java-native-access/jacob/releases
- 下载最新的
jacob-x.x.x.zip文件。jacob-1.21.zip。
-
配置 Jacob 库
- 解压下载的 zip 文件,你会看到
jacob.jar和jacob-x.x.x-x64.dll(或jacob-x.x.x-x86.dll)。 jacob.jar:这是 Java 的库文件,需要添加到你的项目的 classpath 中。.dll文件:这是 JNI 的本地库文件。- 如果你使用的是 64位 的 JDK 和 64位 的操作系统,请使用
jacob-1.21-x64.dll。 - 如果你使用的是 32位 的 JDK 和 32位 的操作系统,请使用
jacob-1.21-x86.dll。 - 重要:JDK 的位数必须与 DLL 的位数一致,否则会报
UnsatisfiedLinkError。
- 如果你使用的是 64位 的 JDK 和 64位 的操作系统,请使用
- 解压下载的 zip 文件,你会看到
-
放置 DLL 文件
(图片来源网络,侵删)- 方法一(推荐,便于开发):将 DLL 文件复制到你的 Java 项目的
src/main/resources目录下,Maven 或 Gradle 在打包时会自动将其复制到最终的输出目录(如target/classes或build/classes)。 - 方法二(运行时指定):将 DLL 文件放在一个固定的路径(
C:\jacob_dll),然后在运行 Java 程序时,通过-Djava.library.path="C:\jacob_dll"参数来指定其位置。 - 方法三(系统路径):将 DLL 文件所在的目录添加到系统的
PATH环境变量中,不推荐,因为可能污染全局环境。
- 方法一(推荐,便于开发):将 DLL 文件复制到你的 Java 项目的
第 2 步:编写 Java 代码
我们将创建一个简单的 Swing 应用,其中包含一个由 ActiveX 控件驱动的浏览器窗口。
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import javax.swing.*;
import java.awt.*;
/**
* 一个使用 Jacob 在 Java Swing 中嵌入 ActiveX WebBrowser 控件的示例。
*/
public class ActiveXBrowserExample {
public static void main(String[] args) {
// 确保在事件调度线程中创建和显示 GUI
SwingUtilities.invokeLater(() -> {
// 创建主窗口
JFrame frame = new JFrame("Java 调用 ActiveX WebBrowser 示例");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
// 创建一个面板来放置 ActiveX 控件
JPanel panel = new JPanel(new BorderLayout());
frame.setContentPane(panel);
try {
// 1. 创建 ActiveX 组件对象
// CLSID 是 WebBrowser 控件的唯一标识符
// 可以从系统注册表中找到,或在网上搜索 "WebBrowser CLSID"
String clsidWebBrowser = "{8856F961-340A-11D0-A96B-00C04FD705A2}";
ActiveXComponent webBrowser = new ActiveXComponent(clsidWebBrowser);
// 2. 获取控件的 Dispatch 对象,用于调用其方法
Dispatch browser = webBrowser.getObject();
// 3. 将 ActiveX 控件嵌入到 Swing 容器中
// 这是 Jacob 的一个关键功能,它需要一个 AWT 的 Container
// panel 是一个 Swing 的 JPanel,但它继承自 AWT 的 Container
Handle handle = new Handle(panel);
Variant result = Dispatch.call(browser, "Navigate", "http://www.baidu.com");
// 将控件与句柄关联
Dispatch.put(browser, "Parent", handle.getHandle());
// 4. 将包含 ActiveX 控件的面板添加到主窗口
panel.add(handle, BorderLayout.CENTER);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(frame, "初始化 ActiveX 控件失败!\n请确保已正确安装 Jacob DLL 并位数匹配。", "错误", JOptionPane.ERROR_MESSAGE);
}
// 显示窗口
frame.setVisible(true);
});
}
/**
* 一个内部类,用于封装 AWT Handle,这是 Jacob 将 ActiveX 控件嵌入到 Swing 容器所需的关键部分。
* 它本质上是一个 Windows 窗口的句柄。
*/
static class Handle extends java.awt.Component {
public Handle(Container parent) {
parent.add(this);
}
public long getHandle() {
return this.getHandle();
}
}
}
第 3 步:配置项目并运行
如果你使用 Maven (推荐)
在 pom.xml 文件中添加 jacob.jar 的依赖:
<dependencies>
<!-- Jacob 依赖 -->
<dependency>
<groupId>net.sf.jacob-project</groupId>
<artifactId>jacob</artifactId>
<version>1.21</version>
<!-- scope provided 表示运行时需要,但打包时由 Maven 处理 -->
<scope>provided</scope>
</dependency>
</dependencies>
确保你的 Maven 项目结构是标准的,并且将 jacob-x.x.x-x64.dll 放在 src/main/resources 目录下,Maven 在构建 jar 包时,可以使用 maven-resources-plugin 来将 DLL 文件复制到 target/classes 目录,这样运行时就能自动找到它。
运行程序
- 编译你的 Java 代码。
- 运行生成的
.class文件,确保 JVM 能找到jacob.jar和.dll文件。- 如果使用 IDE (如 IntelliJ IDEA 或 Eclipse),只需将
jacob.jar添加为库,并将 DLL 放在resources目录下,IDE 通常会自动处理路径。 - 如果通过命令行运行:
# 假设 DLL 在 target/classes 目录下 java -cp ".;target/classes;jacob.jar" com.your.package.ActiveXBrowserExample
注意:Windows 下路径分隔符是 。
- 如果使用 IDE (如 IntelliJ IDEA 或 Eclipse),只需将
运行成功后,你应该会看到一个窗口,其中显示的是百度主页,而这个窗口是由 ActiveX WebBrowser 控件渲染的。
其他调用方法简介
除了 Jacob,还有其他一些技术,但它们各有缺点,通常不作为首选。
JACOB (Java-ActiveX Bridge)
- 注意:这不是 Jacob,是另一个项目,现在已经比较陈旧,不推荐使用。
Apache POI for Office (特殊场景)
如果你调用的是 Microsoft Office 的 ActiveX 自动化接口(比如用 Java 控制 Excel),Apache POI 通常是更好的选择,POI 封装了复杂的 COM 调用,提供了更高级、更稳定的 API 来操作 Office 文档,而不是让你直接去调用底层的 COM 方法,POI 内部可能也使用了类似 Jacob 的技术,但它为开发者提供了更友好的接口。
商业解决方案 (如 J-Integra)
- 优点:功能更强大,支持更复杂的情况,技术支持好。
- 缺点:价格昂贵,对于大多数项目来说成本过高。
重要注意事项和局限性
- 平台限制:这是最关键的一点。ActiveX 是 Windows 独有的技术,任何使用 Jacob 调用 ActiveX 的 Java 程序,只能在 Windows 操作系统上运行,这在跨平台是硬伤。
- 位数匹配:JDK 的位数 (32/64) 必须与 Jacob DLL 的位数以及你调用的 ActiveX 控件的位数(在注册表中可见)完全一致,不匹配会导致
UnsatisfiedLinkError。 - 线程问题:COM 组件不是线程安全的,Jacob 的文档建议,所有的 COM 调用都应该在同一个线程(通常是主线程或一个专门的 COM 线程)中进行,在 Swing 中,通常在 Event Dispatch Thread (EDT) 中进行初始化和操作是安全的。
- 依赖环境:目标机器上必须安装了你要调用的 ActiveX 控件,要调用 WebBrowser,目标机器上必须有 Internet Explorer。
- 错误处理:COM 调用可能会抛出各种
ComFailException,需要进行适当的异常捕获和处理。
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Jacob | 开源、免费、简单、轻量 | 仅限 Windows、需要手动处理 DLL | 绝大多数需要调用通用 ActiveX 的 Java 项目 |
| Apache POI | 高级 API、稳定、专为 Office 设计 | 不适用于通用 ActiveX,仅限 Office 文档操作 | Java 程序需要自动化操作 Word, Excel, PowerPoint 时 |
| 商业方案 | 功能强大、支持好、稳定 | 价格昂贵 | 对稳定性和功能有极高要求的大型企业项目 |
对于绝大多数开发者来说,Jacob 是在 Java 中调用 ActiveX 控件的最佳和最实用的选择,请务必遵循其步骤,特别是关于 DLL 文件位数和放置位置的要求。
