【问题标题】:MATLAB + JNI = error?MATLAB + JNI = 错误?
【发布时间】:2009-07-22 22:06:30
【问题描述】:

有人使用 MATLAB 的 javaObject() 函数和使用 JNI 的 JAR 文件吗?

我正在尝试让 JHDF5 运行,当它尝试使用 jhdf5.dll 获取访问权限时,它似乎会爆炸,所以我真的不知道下一步该做什么。 :(

编辑:我试图读取基本的 HDF5 文件。我有自己的自定义 Java 代码,可以使用 HDF5 并需要 JHDF5 库。另外,我的第一个问题是是否有人成功使用过它。如果不是,那么我可能正在打一场失败的战斗。如果是这样,那么至少它给了我希望。我试试调试,比在Eclipse下调试常规Java代码难度很大。

更新:好的,具体如下。我做了一个非常短的测试类,它的故障模式与我的复杂程序相同。看起来我的 Java 类由于某种原因无法访问 HDF5 静态常量。

我的 MATLAB javaclasspath 设置为包含我的 test-hdf5.jar 和 Test1.java(如下),以及同一目录中的文件 jhdf5.jar、jhdf5.dll、jhdf5obj.jar 和 jhdfobj.jar。

源文件Test1.java:

package com.example.test.hdf5;

import ncsa.hdf.hdf5lib.H5;
import ncsa.hdf.hdf5lib.HDF5Constants;
import ncsa.hdf.hdf5lib.exceptions.HDF5LibraryException;
import ncsa.hdf.object.FileFormat;
import ncsa.hdf.object.h5.H5File;

public class Test1 {
    public Test1 () {}

    public static void main(String args[])
    {
        Test1 test = new Test1();
        if (args.length < 2)
        {

        }
        else if ("h5file".equals(args[0]))
        {
            test.testH5File(args[1]);
        }
        else if ("h5f".equals(args[0]))
        {
            test.testH5F(args[1]);          
        }
    }


    public void testH5File(String filename) {
        H5File file;
        try
        {
            file = (H5File) new H5File().createFile(
                    filename, FileFormat.FILE_CREATE_OPEN);
            file.close();
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    public void testH5F(String filename) {
        try {
            int id = H5.H5Fopen(filename, 
                    HDF5Constants.H5F_ACC_RDONLY, HDF5Constants.H5P_DEFAULT);
            H5.H5Fclose(id);
        }
        catch (HDF5LibraryException e) {
            throw new RuntimeException(e);
        }
        catch (NullPointerException e) {
            throw new RuntimeException(e);
        }
    }
}

MATLAB 错误:

>> T=javaObject('com.example.test.hdf5.Test1')

T =

com.example.test.hdf5.Test1@c9a375

>> T.testH5F('c:/tmp/espdf/jj11copy.hdf5')
java.lang.UnsatisfiedLinkError: no jhdf5 in java.library.path
    at java.lang.ClassLoader.loadLibrary(Unknown Source)
    at java.lang.Runtime.loadLibrary0(Unknown Source)
    at java.lang.System.loadLibrary(Unknown Source)
    at ncsa.hdf.hdf5lib.H5.<clinit>(H5.java:276)
    at ncsa.hdf.hdf5lib.HDF5Constants.<clinit>(HDF5Constants.java:494)
    at com.example.test.hdf5.Test1.testH5F(Test1.java:46)
Jul 23, 2009 10:38:16 AM ncsa.hdf.hdf5lib.H5 <clinit>

INFO: HDF5 library: jhdf5 resolved to: jhdf5.dll;  NOT successfully loaded from java.library.path

??? Java exception occurred:
java.lang.UnsatisfiedLinkError: ncsa.hdf.hdf5lib.H5.H5dont_atexit()I

    at ncsa.hdf.hdf5lib.H5.H5dont_atexit(Native Method)

    at ncsa.hdf.hdf5lib.H5.<clinit>(H5.java:288)

    at ncsa.hdf.hdf5lib.HDF5Constants.<clinit>(HDF5Constants.java:494)

    at com.example.test.hdf5.Test1.testH5F(Test1.java:46)


>> T.testH5F('c:/tmp/espdf/jj11copy.hdf5')
??? Java exception occurred:
java.lang.NoClassDefFoundError: Could not initialize class ncsa.hdf.hdf5lib.HDF5Constants

    at com.example.test.hdf5.Test1.testH5F(Test1.java:46)


>> T.testH5File('c:/tmp/espdf/jj11copy.hdf5')
??? Java exception occurred:
java.lang.NoClassDefFoundError: Could not initialize class ncsa.hdf.hdf5lib.HDF5Constants

    at ncsa.hdf.object.h5.H5File.<init>(H5File.java:167)

    at ncsa.hdf.object.h5.H5File.<init>(H5File.java:106)

    at com.example.test.hdf5.Test1.testH5File(Test1.java:34)

以防万一,这是我正在使用的 ant 构建文件。 JHDF5 .jar 文件和 .dll 在我的lib 目录中;它们被复制到创建我自己的 .jar 文件的 dist 目录中。

<?xml version="1.0"?>
<project default="all" name="test-hdf5">
  <description>some libraries to use later</description>

  <property name="srcDir" location="src"/>
  <property name="buildDir" location="bin"/>
  <property name="distDir" location="dist"/>
  <property name="libDir" location="lib"/>

  <target name="init">
    <tstamp/>
    <mkdir dir="${buildDir}"/>
    <mkdir dir="${distDir}"/>
  </target>
      <path id="antclasspath">
        <fileset dir="${libDir}">
            <include name="*.jar"/>
        </fileset>
    </path>  

    <target name="compile" depends="init">
        <javac srcdir="${srcDir}"
               destdir="${buildDir}"
               debug="on"
               target="1.6"
               classpathref="antclasspath"
        />
      </target>

  <target name="dist" depends="compile">
    <copy todir="${buildDir}">
        <fileset dir="${srcDir}">
            <include name="*.properties" />
        </fileset>
    </copy>
    <copy todir="${distDir}">
       <fileset dir="${libDir}">
           <include name="*.dll" />
           <include name="*.jar" />
       </fileset>
    </copy>
    <jar destfile="${distDir}/test-hdf5.jar" basedir="${buildDir}"
        includes="**">
      <manifest>
        <attribute name="Built-By" value="${user.name}"/>
        <attribute name="Main-Class" value="com.example.test.hdf5.Test1" />
        <attribute name="Class-Path" value=". ./jhdf5.jar ./jhdfobj.jar ./jdhf5obj.jar" />
      </manifest>
    </jar>
  </target>

  <target name="all" depends="dist" />

  <target name="clean" >
    <delete dir="${buildDir}" />
  </target>
</project>

【问题讨论】:

  • 常见问题:你做了什么?你期待什么结果?实际结果在哪些方面与您的预期不一致? “看起来像炸弹”根本没有告诉读者任何事情。
  • 你尝试运行的代码和你得到的错误信息会有很大帮助。
  • 这并不直接涉及 JNI 问题,但您可以将 Eclipse 调试器附加到 Matlab 的嵌入式 JVM 以调试在 Matlab 中运行的 Java 代码。在您启动 Matlab 的目录中创建一个名为“java.opts”的文件,并将这一行放入其中。 -agentlib:jdwp=server=y,transport=dt_socket,address=9999 然后启动 Eclipse 和 Matlab。 Matlab 将在启动时阻塞并等待您附加调试器。另外,我同意其他评论者的观点。需要更多详细信息,最好是准确的代码和错误消息。
  • @gnovice:同意;值得庆幸的是,使用简短的程序很容易重现故障。否则我将无法发布专有代码:/

标签: java matlab java-native-interface


【解决方案1】:

JHDF5 在 Java 端使用一些愚蠢的搜索逻辑来加载 dll。它可以工作,除非它不工作,这通常是。与许多 HDF5 细节一样,底层逻辑没有记录。

我这样做了:获取 JHDF5 Java 源代码,删除了试图加载 jhdf5.dll 的愚蠢 AI(它位于 ncsa/hdf/hdf5lib/H5.java 文件中,大约第 230-290 行的 static 部分) ,并将其替换为显式的 System.load("full/path/to/the/jhdf5.dll"); 语句。然后重新编译jhdf5.jar。也许不漂亮,但效果很好。

此外,查看源代码,似乎如果您将名为H5_LIBRARY_NAME_PROPERTY_KEY 的系统属性设置为指向 dll,它可能会被加载。例如,您可以通过使用 -D 开关启动 jvm 来设置系统属性,例如:

java -DH5_LIBRARY_NAME_PROPERTY_KEY=path/to/the/jhdf5.dll -jar yourapp.jar

不过没试过。

【讨论】:

  • 不幸的是,在 MATLAB 中您不启动 jvm,它会自行启动。如果可以的话,我不知道如何设置系统属性。
  • 啊。呃。我可以做 java.lang.System.setProperty('ncsa.hdf.hdf5lib.H5.hdf5lib',path_to_jhdf5_dll);这行得通!
【解决方案2】:

Matlab 对此非常复杂,以上是正确的,类路径不用于 dll。您可以使用像上面这样的环境解决方案,但也可以使用更多 MATLAB 特定的变量。文件 librarypath.txt 能够列出包含 MATLAB 可用的任何 dll 的文件夹。它在启动时执行,因此不能动态添加。要编辑库路径,请在 MATLAB 命令行上运行 edit librarypath.txt

【讨论】:

    【解决方案3】:

    dll 可能不在 java 类路径上。尝试将其目录添加到系统的 PATH 环境变量中。或者更好的是,只需使用 hd5read/write 函数。

    【讨论】:

    • 不是这个;我可以从命令提示符或 Eclipse 调试器中运行我的 .jar 文件。我尝试将 DLL 的副本放入路径上的目录中,但没有改变任何内容。
    【解决方案4】:

    类路径不用于 dll。它们需要位于 PATH 环境变量 (windows) 或 LD_LIBRARY_PATH (linux) 中。您可能还想使用 Depends (Windows, http://www.dependencywalker.com) 或 ldd (linux) 验证 DLL 本身的相对位置和依赖关系是否正确

    【讨论】:

    • 不是这个;我可以从命令提示符或 Eclipse 调试器中运行我的 .jar 文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多