【问题标题】:Return value from jar file created from Matlab从 Matlab 创建的 jar 文件返回值
【发布时间】:2015-02-07 02:02:11
【问题描述】:

我有一个 Matlab 代码,它最后计算了一个索引向量。我使用库编译器将 matlab 代码编译为 java 包 .jar 文件。我导出了 jar 文件以便为我的主要 Java 项目运行它。包类的名称是 Epidemic。我导入了 jar 文件(将其添加为外部 jar)。在主代码中,我尝试创建我的类的对象(在 jar 文件中)。我已经将类的名称定义为 Epidemic。因此,我的代码:

import epidemic.Epidemic;
...
public static void main(String[] args) throws IOException {

    List<Double> list1 = new ArrayList<Double>();
    List<Double> list2 = new ArrayList<Double>();

    Epidemic object = new Epidemic(); 
    object.epidemic(list1, list2);
    System.out.println(list1);
}

我使用 project->Libraries 右键单击​​添加外部 jar 将 .jar 文件添加到 java 项目。 Netbeans 自动检测对象的方法。但是我收到以下错误:

Exception in thread "main" java.lang.NoClassDefFoundError:  
com/mathworks/toolbox/javabuilder/internal/MWComponentInstance
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at twittertrendsetters.TwitterTrendSetters.main(TwitterTrendSetters.java:70)
Caused by: java.lang.ClassNotFoundException:
com.mathworks.toolbox.javabuilder.internal.MWComponentInstance
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 13 more

这里有什么问题?我应该添加其他东西以使 jar 正常工作吗?

编辑:我将位于 MATLABROOT/toolbox/javabuild/jar/javabuild.jar 中的 .jar 文件添加到我的类路径和它似乎可以工作的类中。现在我面临另一个问题。当我打印基于 html 文档的 list1 获取 matlab .m 文件的输出时,我得到了一个空的 arrayList。 Matlab 函数返回一个双精度数组 Nx1。如何将其正确解析为 java arrayList。

我的matlab代码:

function eP = epidemic() // zero input

graph = dlmread('graph.edges'); //a graph
graph_ids=importdata('cms_V3_id.txt');  // indexes of the graph

for index = 1:length(graph)
 grph(index,1) = find(graph_ids == graph(index,1));
 grph(index,2) = find(graph_ids == graph(index,2));
end
grph(:,3)= graph(:,3);

grph(end + 1, :, :) = [max(max(grph)) max(max(grph)) 1 ];
grph =  spconvert(grph);

[S, prev] = brutte_topk2(grph, 3707); //function approximate pagerank result
eP = graph_ids(S); // returning a list of indexes

我尝试使用您的方法。我创建了一个 OBject 表并将结果解析到其中。

    Epidemic object = new Epidemic(); 
    Object[] result;
    result = object.epidemic(1);
    System.out.println((Double)result[0]);

但是我得到 javabuilder.MWNumericArray 不能转换为 java.lang.Double。当我只打印结果时

【问题讨论】:

    标签: java matlab jar matlab-deployment matlab-compiler


    【解决方案1】:

    您需要在 Java 项目类路径中添加两件事:

    • 您在 MATLAB 代码中created 部署的 JAR 文件。
    • Java Builder 自己的 JAR 文件。如果您在目标机器上安装了 MATLAB,则可以在 $MATLABROOT\toolbox\javabuilder\jar\javabuilder.jar 中找到它们,否则安装适当的 MCR 运行时(免费提供),并在类似路径中找到 JAR 文件。

    有关完整说明,请参阅 here


    编辑:

    为了完整起见,下面是一个工作示例。

    1. 假设我们有以下 MATLAB 函数,它返回一个数字数组。

      epidemic.m

      function list = epidemic()
          list = randi(100, [1, 10]);
      end
      
    2. 使用applicationCompiler MATLAB 应用程序,创建一个新项目来构建“Java 包”。将上述函数添加到项目中,设置类名和方法名,然后构建包。我们应该得到一个 JAR 文件,比如:Epidemic.jar

    3. 接下来我们创建一个Java程序来测试上面的包。例如:

      TestEpidemic.java

      import java.util.*;
      import com.mathworks.toolbox.javabuilder.*;  // MATLAB Java Builder
      import Epidemic.*;                           // our compiled package
      
      public class TestEpidemic {
          public double[] getArray() throws MWException {
              Epidemic obj = null;
              Object[] out = null;
              double [] arr = null;
              try {
                  obj = new Epidemic();
                  out = obj.epidemic(1);  // request one output
                  arr = (double[]) ((MWArray)out[0]).getData();
              } catch (MWException e) {
                  System.out.println("Exception: " + e.toString());
              } finally {
                  MWArray.disposeArray(out);
                  obj.dispose();
              }
              return arr;
          }
      
          public static void main (String[] args) {
              try {
                  TestEpidemic e = new TestEpidemic();
                  double[] arr = e.getArray();
                  for(double x : arr) {
                      System.out.println(x);
                  }
              } catch (Throwable t) {
                  t.printStackTrace();
              }
          }
      }
      
    4. 最后我们编译并运行测试程序:

      javac.exe -classpath "%MATLABROOT%\toolbox\javabuilder\jar\javabuilder.jar";.\Epidemic.jar TestEpidemic.java
      
      java.exe -classpath .;"%MATLABROOT%\toolbox\javabuilder\jar\javabuilder.jar";.\Epidemic.jar TestEpidemic
      

      您应该会看到一个包含 10 个双精度数的数组。

    【讨论】:

    • 在 matlabroot 我有 bot javabuilder/jar 文件夹和 javabuilder/jar/win64。我必须将两个文件夹中的哪一个添加到路径中?此外,我必须将它添加到环境路径或类路径?有什么区别?
    • @FereRes:不,您必须将 JAR 文件 添加到您的 NetBeans 项目(将它们添加到 Java classpath),就像您执行其他文件一样。您应该选择与机器架构、JVM 和 MATLAB(32 位或 64 位)相匹配的版本。
    • 是的,我认为这解决了问题。但是现在我遇到了另一个问题:线程“主”中的异常 ... Matlab M-code Stack Trace ...文件 C:\Users\chrathan\AppData\Local\Temp\chrathan\mcrCache8.3\epidem0\epidemic\流行病.m,名称流行病,第 20 行。com.mathworks.toolbox.javabuilder.MWException
    • @FereRes:这是 MATLAB 代码抛出的运行时异常。可能是你给函数输入了错误的类型吗?检查epide‌​mic.m 文件第 20 行中的原始代码...
    • 在下面的 .m 文件中,它实际上是返回整数列表 eP 函数 eP =流行病()。在 java 代码中,我创建了一个对象 Epidemic object = new Epidemic()。下一步使用流行病功能。在 html 文档中,它向我展示了使用该方法的三种方法。要么使用两个列表作为方法参数,要么使用两个 Object obj 或一个整数和一个 Object。在 Matlab 代码中,我没有任何论据。因此,当我使用两个列表作为参数时,它会显示上一个错误。
    【解决方案2】:

    如果 JAR 文件包含 main 方法,则它只能返回退出代码。返回值的类型是整数。如果你使用System.exit(returnCode),你就可以做到这一点。

    如果你的意思是你有另一个项目要嵌入这个项目,你必须摆脱正确的依赖关系,只需从你想要的 JAR 中调用方法。

    【讨论】:

    • 我有一个 java 项目,我想在其中嵌入一个 jar 文件(来自 matlab 代码)。是否可以在 matlab 代码中创建一个函数,该函数将返回一个整数向量,并将其从 jar 调用到 java 代码?
    • @FereRes 所以你有一个来自 matlab 的 JAR 文件。包含什么?代码?其它文件?主要方法?如果它是带有类的普通 JAR 文件,您可以转到您的项目并编辑包含的库。
    • 在 Matlab 代码中,我得到了一个函数,我使用类名将其编译为 jar,例如 class1。如何查看 jar 文件的结构?我的意思是我不知道里面是什么。
    • @FereRes 比如用7Zip解压就行了。
    猜你喜欢
    • 2010-10-22
    • 2015-04-24
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 2021-05-08
    • 2015-09-09
    相关资源
    最近更新 更多