使用 MATLAB Engine API (推荐)
这是 MathWorks 官方推荐的方式,也是最强大、最灵活的方式,它允许你的 Java 应用程序在运行时启动一个 MATLAB 进程,并直接调用其中的函数和脚本,传递和接收数据。
核心原理: Java 通过一个本地接口与 MATLAB 的核心引擎进行通信,Java 发送命令和数据给 MATLAB 引擎,引擎执行后返回结果。
优点:
- 功能最全:可以调用任何 MATLAB 函数(包括内置函数和自定义函数),甚至可以执行脚本。
- 双向交互:可以轻松地将 Java 对象(如数组)传递给 MATLAB,并将 MATLAB 的结果(如数值、矩阵、结构体)传回 Java。
- 官方支持:由 MathWorks 官方维护,稳定性和兼容性最好。
缺点:
- 依赖 MATLAB 环境:目标机器上必须安装 MATLAB。
- 性能开销:启动 MATLAB 进程需要时间,进程间通信也有一定的性能开销,不适合极高频率的调用。
详细步骤与代码示例
前提条件:
- 已安装 MATLAB。
- 在 MATLAB 中进行配置,让 Java 能找到 MATLAB 的库。
- 打开 MATLAB。
- 在命令窗口输入
matlab -desktop -jvm确保启动了 JVM。 - 运行
matlab.engine.shareEngine来共享引擎实例(可选,但推荐)。 - 关键步骤:找到 MATLAB 的安装路径,
C:\Program Files\MATLAB\R2025a\extern\engines\java,将这个路径添加到你的 Java 项目的类路径中。
示例代码:
假设我们有一个简单的 MATLAB 函数 add.m:
% add.m
function sum = add(a, b)
sum = a + b;
end
Java 代码
import matlab.engine.*;
public class MatlabEngineExample {
public static void main(String[] args) {
try {
// 1. 启动 MATLAB 引擎
// 这个调用可能会阻塞,直到 MATLAB 引擎完全启动
System.out.println("Starting MATLAB Engine...");
MatlabEngine eng = matlab.engine.MatlabEngine.startMatlab();
// 2. 调用 MATLAB 函数
// 调用 add(5, 10),并获取第一个输出参数
System.out.println("Calling MATLAB function add(5, 10)...");
int result = eng.feval("add", 5, 10);
System.out.println("Result from MATLAB: " + result);
// 3. 传递数组
System.out.println("\nPassing an array to MATLAB...");
double[] javaArray = {1.0, 2.0, 3.0, 4.0, 5.0};
// 将 Java 数组转换为 MATLAB 的 double 类型数组
// MATLAB 的 double 数组对应 Java 的 double[].class
eng.put("matlabArray", javaArray); // 将 javaArray 变量存入 MATLAB 工作空间,名为 matlabArray
// 在 MATLAB 中计算数组平方和
double sumOfSquares = eng.feval("sum", eng.feval("power", "matlabArray", 2));
System.out.println("Sum of squares from MATLAB: " + sumOfSquares);
// 4. 执行脚本
System.out.println("\nExecuting a MATLAB script...");
eng.eval("disp('Hello from MATLAB script!');");
eng.eval("x = 100; y = 200; z = x * y;");
int scriptResult = eng.getVariable("z"); // 从 MATLAB 工作空间获取变量 z
System.out.println("Result from script (z = x * y): " + scriptResult);
// 5. 关闭 MATLAB 引擎
System.out.println("\nClosing MATLAB Engine...");
eng.close();
} catch (MatlabEngineException e) {
System.err.println("Error with MATLAB Engine: " + e.getMessage());
e.printStackTrace();
}
}
}
如何编译和运行
-
IDE (如 IntelliJ IDEA 或 Eclipse):
- 创建一个新的 Java 项目。
- 将
matlabengine.jar(位于MATLAB\extern\engines\java目录下) 添加到项目的库中。 - 将
MATLAB\bin\win64(或对应你的系统的目录,如darwin或linux) 添加到 JVM 的java.library.path,这可以通过在 VM options 中添加-Djava.library.path="C:\Program Files\MATLAB\R2025a\bin\win64"来实现。 - 将上面的 Java 代码粘贴到主类中,然后运行。
-
命令行:
# 假设 matlabengine.jar 在当前目录,.dll/.so 文件在系统路径中 javac -cp ".;C:\Program Files\MATLAB\R2025a\extern\engines\java\matlabengine.jar" MatlabEngineExample.java java -cp ".;C:\Program Files\MATLAB\R2025a\extern\engines\java\matlabengine.jar" MatlabEngineExample
将 MATLAB 代码编译为 Java 库 (JAR)
这种方式将你的 MATLAB 函数编译成一个独立的 Java JAR 文件,这样你的 Java 应用程序就可以像调用普通 Java 类一样调用它,而无需在运行时安装 MATLAB。
核心原理:
使用 MATLAB 的 Compiler ( mcc) 工具,将 .m 文件编译成 Java 可调用的代码,并打包成 JAR 文件,这本质上是将 MATLAB 代码翻译成 Java 字节码。
优点:
- 独立运行:最终应用不依赖 MATLAB 环境,只需安装 JRE。
- 性能较好:没有进程间通信的开销,直接调用本地代码。
缺点:
- 功能受限:只能编译函数,不能直接编译脚本,某些高级 MATLAB 特性(如特定工具箱函数)可能不被支持。
- 编译过程复杂:需要配置 Compiler SDK,并且生成的 JAR 文件可能依赖其他第三方库。
- 版本兼容性:编译时使用的 MATLAB 版本和运行时 JRE 版本需要匹配。
详细步骤与代码示例
前提条件:
- 已安装 MATLAB Compiler SDK (通常是 MATLAB 安装时的一个可选组件)。
- 需要一个
.m文件。
示例代码:
还是用 add.m 函数。
编译步骤
- 打开 MATLAB。
- 在命令窗口输入以下命令来编译
add.m:% -d: 指定输出目录 % -W java:JAR -T jar:指定生成类型为 JAR % add: 要编译的 MATLAB 函数名 % add_class: 生成的 Java 类名 mcc -d 'output_folder' -W java:MatlabAddJAR -T jar:add add.m
执行后,MATLAB 会在
output_folder目录下生成MatlabAddJAR.jar以及一些相关的.class文件和依赖库。
Java 代码
import matlab.add_jar.*; // 导入编译后生成的包
public class MatlabJARExample {
public static void main(String[] args) {
try {
// 创建 MATLAB 库的实例
MatlabAddJAR matlabLib = new MatlabAddJAR();
// 调用编译后的函数
// 注意:函数名变成了大开头的 "Add"
Object[] result = matlabLib.Add(15, 25);
// 结果是一个 Object 数组,第一个元素是返回值
int sum = (Integer) result[0];
System.out.println("Result from compiled JAR: " + sum);
} catch (Exception e) {
System.err.println("Error calling compiled MATLAB function: " + e.getMessage());
e.printStackTrace();
}
}
}
如何编译和运行
- 将编译生成的
MatlabAddJAR.jar以及它依赖的所有.jar文件(在output_folder目录下)添加到你的 Java 项目的类路径中。 - 像运行普通 Java 项目一样运行上述代码。
通过进程调用 (最简单,但功能最弱)
这种方式不使用任何官方 API,而是通过 Java 的 Runtime.exec() 或 ProcessBuilder 来启动 MATLAB 进程,并像在命令行中一样执行命令。
核心原理: Java 启动一个独立的 MATLAB 进程,通过标准输入向它发送命令,通过标准输出读取结果。
优点:
- 实现简单:无需复杂的配置,只需要能调用
matlab.exe。 - 不依赖 API:不使用
matlabengine.jar。
缺点:
- 功能极弱:无法传递复杂的数据结构(如多维数组),只能通过字符串命令和文件进行交互。
- 通信困难:解析标准输出非常繁琐且容易出错。
- 性能差:每次调用都需要启动和销毁一个完整的 MATLAB 进程,开销巨大。
详细步骤与代码示例
前提条件:
- 系统环境变量
PATH中包含 MATLAB 的bin目录,以便能找到matlab.exe。
示例代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class MatlabProcessExample {
public static void main(String[] args) {
try {
// 构建命令
// -r 后面跟着要执行的 MATLAB 命令,用分号隔开
// -nodisplay -nosplash 表示不显示图形界面
String[] command = {
"matlab",
"-nodisplay",
"-nosplash",
"-r", "add(5, 10); disp('Process finished'); exit;"
};
// 启动进程
Process process = Runtime.getRuntime().exec(command);
// 读取进程的标准输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
System.out.println("Output from MATLAB process:");
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 读取进程的错误输出
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
System.out.println("\nErrors from MATLAB process:");
while ((line = errorReader.readLine()) != null) {
System.err.println(line);
}
// 等待进程结束
int exitCode = process.waitFor();
System.out.println("\nMATLAB process exited with code: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
总结与对比
| 特性 | MATLAB Engine API | 编译为 JAR | 通过进程调用 |
|---|---|---|---|
| 依赖环境 | 必须安装 MATLAB | 仅需 JRE | 必须安装 MATLAB |
| 功能完整性 | 最强 (所有函数、脚本、数据类型) | 较强 (仅编译的函数) | 最弱 (仅命令行) |
| 性能 | 中等 (有进程通信开销) | 高 (直接调用) | 低 (进程启动/销毁开销大) |
| 易用性 | 配置稍复杂,调用简单 | 编译复杂,调用简单 | 配置简单,调用和解析困难 |
| 适用场景 | 开发阶段、需要交互式计算、功能要求高 | 部署阶段、追求高性能和独立性 | 快速原型、执行简单脚本、无法使用 API 时 |
如何选择?
- 如果你正在开发一个原型,或者你的应用环境就是安装了 MATLAB 的服务器/工作站,并且需要调用大量 MATLAB 函数,首选 MATLAB Engine API,这是最灵活、最强大的方案。
- 如果你需要将你的应用分发给最终用户,而这些用户没有安装 MATLAB,那么选择编译为 JAR 的方式,这是部署和分发的标准方案。
- 如果你只是想偶尔执行一个非常简单的 MATLAB 命令,并且不想引入复杂的依赖,可以考虑通过进程调用,但要准备好处理字符串解析的麻烦,对于大多数严肃的应用,不推荐此方法。
