java 调用 matlab

  • 前言
  • 系统环境说明
  • 开发(windows下)
  • 部署(linux下)
  • 遇到的问题


前言

最近遇到个变态需求,使用系统数据通过matlab绘图,并将图片上传系统。作为一个java程序员对于matlab了解的实在少,于是就上网寻找答案,但是找到的东西都不够全面,所以决定自己记录一下这个过程。

系统环境说明

这点对于java调用matlab来说至关重要,如果出现差别就可能会使得调用不成功

  • 开发环境

运行环境

版本

操作系统类型

jdk

1.8.0.131

windows x64

matlab

R2017b

windows x64

这里matlab自带jdk的版本是1.8.0.121与开发windows系统的版本相近,开发环境java调用matlab库会直接调用安装的matlab环境,不会调用MCR(matlab运行时环境)

  • 部署环境

运行环境

版本

操作系统类型

jdk

1.8.0.191

centos x64

matlab MCR

R2017b

centos x64

线上部署一般使用的是linux服务器,没有图形化界面,因此一般安装运行时环境及MCR,当程序代码移植到服务器就需要去调用MCR环境->

开发(windows下)

  • matlab安装(R2017b)
    matlab安装就不介绍了,可自行百度
  • 接口设计
    接口设计也是比较重要的一环,决定java端传什么样的参数给matlab的程序,可传的参数有单个数值,字符串,矩阵等。

带参数返回值

function [ data ] imageCreate(name,time,data,storePath)

这里data是返回值,可以是矩阵,可以是值;name,time,data,storePath是参数,如name可以传string,time可以传double,data可以传矩阵,这都取决于你的matlab程序如何处理这些参数

不带参数返回值

function imageCreate()
  • matlab代码实现
    通过你出色的matlab造诣写一段matlab的代码,然后在本地编译看能不能通过,测试通过后进行下一步
  • 生成jar包
    在matlab命令行窗口输入 depoytool

    选择Library Compiler

    根据提示生成java jar包

还有需要注意的一点是,如果你的matlab程序依赖的别的包,在打成jar时需要将这些依赖打包进去

MATLAB可以和Java联用吗 matlab和java有关系吗_matlab

  • java代码实现
    首先需要将matlab生成的jar导入到java工程,这里以mvn导入方式为例导入jar
    1 、首先在工程目录resources目录下新建lib目录

    2、将matlib javabuilder.jar以及刚才打包好的imageCreate.jar移动到lib目录下
    javabuilder.jar 的路径在matlab安装路径:
    D:\Program Files\MATLAB\R2017b\toolbox\javabuilder\jar
    imageCreate.jar 可以在你生成jar时选择的路径找到
    3、mvn配置
    使用system标签将刚才的jar引入,里面的groupId,artifactId,version可自定义进行标识
<!-- matlab绘图导出jar -->
        <dependency>
            <groupId>com.spaceon</groupId>
            <artifactId>matlab-infocard</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${pom.basedir}/src/main/resources/lib/imageCreate.jar</systemPath>
        </dependency>
        <!-- matlab javabuilder-->
        <dependency>
            <groupId>com.spaceon</groupId>
            <artifactId>matlab-jb</artifactId>
            <version>1.0</version>
            <scope>system</scope>
            <systemPath>${pom.basedir}/src/main/resources/lib/javabuilder.jar</systemPath>
        </dependency>
package com.face;

import imageCreate.ImageCreate;
import com.mathworks.toolbox.javabuilder.MWClassID;
import com.mathworks.toolbox.javabuilder.MWException;
import com.mathworks.toolbox.javabuilder.MWNumericArray;

/**
 * @author baixuezhi
 * @date 2022/7/1
 */
public class Test {
    public static void main(String[] args) throws MWException {

        ImageCreate ic = new ImageCreate();
        String[][] arr = {{"20220601000203","-3.775923","82.507018","27.9"},
                {"20220601010203","-3.784745","82.516632","28.1"},
                {"20220601020203","-3.791435","82.528632","28.5"},
                {"20220601030203","-3.798773","83.540260","29.1"},
                {"20220601040203","-3.807707","83.546432","29.5"},
                {"20220601050203","-3.817848","84.550345","30.2"},
                {"20220601060203","-3.827710","84.551833","30.5"},
                {"20220601070203","-3.840060","85.551552","31.2"},
                {"20220601080203","-3.853607","85.553405","31.5"},
                {"20220601090203","-3.868455","85.558052","32.3"},
                {"20220601100203","-3.881727","86.561080","32.5"},
                {"20220601110203","-3.893028","86.563507","33.5"},
                {"20220601120203","-3.904352","86.566032","34.5"},
                {"20220601140203","-3.904352","87.566032","34.8"}
        };
        //转矩阵
        MWNumericArray matArr = new MWNumericArray(arr, MWClassID.DOUBLE);
        String name= "AMAX121212";
        String time="20220601";
        String path = "C:\\Users\\lenovo\\Desktop\\xxx\\图片\\";
        //生成图片并保存到指定路径
        ic.argosInfoCard(name, s, matArr,path);
    }
}
  • 打包
    在项目pom文件plugins标签加入以下配置
<includeSystemScope>true</includeSystemScope>

例:

<plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.face.webapi.WebApplication</mainClass>
                    <includeSystemScope>true</includeSystemScope>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

部署(linux下)

  • centos 服务器 MCR 安装(R2017b)
    将下载下来的安装包上传到服务器并解压

    在安装目录新建matlab文件夹进行操作
mkdir matlab
mv MCR_R2017b_glnxa64_installer.zip matlab
cd matlab
unzip MCR_R2017b_glnxa64_installer.zip

解压的结果:

MATLAB可以和Java联用吗 matlab和java有关系吗_java_02

安装

./install -mode silent -agreeToLicense yes

MATLAB可以和Java联用吗 matlab和java有关系吗_开发语言_03


安装完成末尾有两种重要提示信息如上图:

1、给matlab mcr 配置环境变量

vim /etc/profile

末尾追加

export LD_LIBRARY_PATH=/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/bin/glnxa64:/usr/local/MATLAB/MATLAB_Runtime/v93/sys/os/glnxa64:

使配置生效

source /etc/profile

2、安装成功的提示

  • 将打包的程序上传centos服务器
    将java项目打包上传到刚才安装了MCR的服务器
  • 运行测试
    验证服务是否可以正常运行

遇到的问题

  • Spring boot出现java.awt.HeadlessException
    这是在开发的时候windows下报的错,在主类添加如下配置即可
static {
    System.setProperty("java.awt.headless","false");
}
  • Exception in thread “AWT-EventQueue-0” java.lang.NoClassDefFoundError: Could not initialize class com.mathworks.common.icons.IconEnumerationUtils
    这个错误比较恶心,我找了好久才找到,问题是matlab运行时common.jar包的依赖与项目中的依赖发生冲突导致,解决有3种方式:
    1、修改common.jar的源码,
    2、解决java项目中的冲突(不好找出冲突的地方),
    3、将项目中该模块独立出来单独部署
  • 还有个问题是,将java打包后上传到服务器,运行的时候报找不到x86(32位)的matlab动态库,让后一直找不到MWMCR类
    这个问题的原因是我的开发环境用的是64位的jdk,但是生产环境用的是32位的jdk,尽管版本完全一直但是就会出现以上错误,导致调用失败,之后将服务器的jdk换成64位的就可以了
  • 将程序移植到linux后图片中的字符(matlab代码)显示不出来,感觉像乱码,但又不像
    这个问题是应为linux系统下没有对应的字体导致的,我的matlab程序代码中的字体为“微软雅黑”,所以在linux下安装对应字体即可参照网址