如何将 MATLAB 源代码导出成 Java 的 JAR 包

  • Post author:
  • Post category:java


运行环境:

  • MATLAB R2022a

  • Java 8(1.8.0_311)

  • Windows 10 教育版 64位

使用混合编程通常都不是好主意,但是有时候会遇到极端的情况。Java 擅长网络编程,MATLAB 擅长数学高级计算与图形化。这种情况下,没办法使用一种编程语言快速完成这两项事情,因此不得不使用 Java、MATLAB 混合编程。这里提供的办法是,将一个 MATLAB 函数文件转化为 Java 的 JAR 包,然后在 Java 中运行这个 JAR 包。

编写这个教程时,笔者已经帮读者几乎踩遍了所有常见的坑。仔细阅读本教程可以减少很多麻烦。



编写 MATLAB 源文件

  1. 这里编写了一个简单的 MATLAB 函数 matlabPlot、matlabPolarplot。这两个函数做的事情很简单,只是调用原生函数用于绘图而已。


    • matlabPlot.m
    function matlabPlot(x,y)
    plot(x,y);
    axis equal;
    

    • matlabPolarplot.m
    function matlabPolarplot(x,y)
    polarplot(x,y);
    



安装 Java

  1. 下面来开始将这个函数文件转化成 JAR 包。在这之前,需要安装 JDK。关于这方面的内容,可见笔者的另一篇博客:


    Java 的下载安装教程:


    https://blog.csdn.net/wangpaiblog/article/details/111466827


    【踩坑提醒】

    • 直到

      MATLAB R2022a

      时,安装的 Java 版本不能超过 8。

    • 需要将 Windows 环境变量

      JAVA_HOME

      的值设成 Java 8 的安装目录。

    • 配置完 Windows 环境变量后,重启 MATLAB 之后才会在 MATLAB 中生效。




制作 JAR 包

  1. 在 MATLAB 命令行窗口输入以下命令。



    deploytool


  2. 在弹出的窗口中选择 Libary Compiler。

    在这里插入图片描述

  3. 在弹出的窗口中选择 Java Package,并添加前面的 MATLAB 函数文件,然后依次填写好 Java 类名等信息,最后点击 Package 生成 JAR 包。

    在这里插入图片描述

  4. 首次打包时,需要按提示保存本次打包配置(格式为

    .prj

    )。

  5. 打包成功会出现如图结果。如果打包失败,需查看失败日志判断原因。比方说,如果没注意笔者前面编写的

    踩坑提醒

    ,则会因为 JDK 的问题引发失败。

    在这里插入图片描述

  6. 如果打包成功,MATLAB 会在与前面打包配置文件同目录下,生成一个以配置文件名为名称的一个文件夹。该文件夹有以下文件(夹):


    • for_redistribution

    • for_redistribution_files_only

    • for_testing

    • PackagingLog.html

    这里不详细介绍各个文件的作用。我们所需要的 JAR 包在文件夹

    for_redistribution_files_only

    下。其它文件均可删除。



找到 MATLAB 的 JAR 包

  1. 但是,

    光有此 JAR 包还不能在我们自己的 Java 程序中运行

    。因为显然,此 JAR 包本质上只会含我们上面写的那么一点儿代码,这肯定是无法运行的。运行肯定还需要 MATLAB 自身对外提供的 SDK,也就是编程时经常所说的运行环境。不过幸运的是,这个 Java 版本的 SDK 在 MATLAB 安装的时候就已经提供了。对于笔者的

    MATLAB R2022a

    ,它在如下目录中。读者需要根据自己 MATLAB 的安装情况找到那个名为

    javabuilder.jar

    的 JAR 包。

    C:\Program Files\MATLAB\R2022a\toolbox\javabuilder\jar\javabuilder.jar
    
  2. 因此,这里只需要

    MatlabUtil.jar



    javabuilder.jar

    即可在我们自己的 Java 程序中运行。


    【踩坑提醒】

    这两个 JAR 包不能在 Java 8 以上的版本运行,否则会发生如下报错:

       Exception in thread "AWT-EventQueue-0": java.lang.IllegalAccessError: superclass access check failed: class com.mathworks.hg.peer.types.HGMotifCheckMenuUI (in unnamed module @0x706bf110) cannot access class com.sun.java.swing.plaf.motif.MotifMenuUI (in module java.desktop) because module java.desktop does not export com.sun.java.swing.plaf.motif to unnamed module @0x706bf110
       	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
       	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012)
       	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
       	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
       	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
       	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
       	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
       	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
       	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
       	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
       	at com.mathworks.hg.peer.MenuPeer.doCreateMenu(MenuPeer.java:142)
       	at com.mathworks.hg.peer.MenuPeer.access$000(MenuPeer.java:32)
       	at com.mathworks.hg.peer.MenuPeer$1.run(MenuPeer.java:131)
       	at com.mathworks.hg.util.HGPeerQueue$HGPeerRunnablesRunner.runit(HGPeerQueue.java:290)
       	at com.mathworks.hg.util.HGPeerQueue$HGPeerRunnablesRunner.runThese(HGPeerQueue.java:318)
       	at com.mathworks.hg.util.HGPeerQueue$HGPeerRunnablesRunner.run(HGPeerQueue.java:335)
       	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
       	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:771)
       	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
       	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
       	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
       	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
       	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:741)
       	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
       	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
       	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
       	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
       	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
    

    Java 允许在同一个操作系统上安装多个版本的 Java。由于 Java 的 IDE 普遍支持在 IDE 中自由选择 Java 版本,所以这可能导致问题。

    如果想确认自己的 Java 程序使用的是哪个版本的 Java,可以在程序使用以下代码之一。

    System.out.println("Java 版本号:" + System.getProperty("java.version"));
    System.out.println("Java 虚拟机规范版本号:" + System.getProperty("java.vm.specification.version"));
    System.out.println("Java 规范版本号:" + System.getProperty("java.specification.version"));
    System.out.println("Java 类路径:" + System.getProperty("java.class.path"));
    System.out.println("Java lib 路径:" + System.getProperty("java.library.path"));
    System.out.println("Java 执行路径:" + System.getProperty("java.ext.dirs"));
    



在 Java 中调用 MATLAB 的 JAR 包

关于这方面的内容,可见笔者的另一篇博客:


如何在 Java 中调用 MATLAB 代码:


https://blog.csdn.net/wangpaiblog/article/details/128293573



版权声明:本文为wangpaiblog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。