Results 1 to 12 of 12
Thread: JNI, Java, Mathematica
- 06-26-2011, 02:57 AM #1
Member
- Join Date
- Jun 2011
- Posts
- 4
- Rep Power
- 0
JNI, Java, Mathematica
I am trying to get a Java method to work in Mathematica; Mathematica provides suitable access to a JVM through J/Link. Everything is working great for my own Java classes. The problem is that the method I need calls a JNI (.dll file). Outside of Mathematica from the "cmd" line, all works great. But calling the method within Mathematica, the JVM returns the following:
Java::excptn: A Java exception occurred: java.lang.UnsatisfiedLinkError: ncsa.hdf.hdf5lib.H5.H5Fcreate(Ljava/lang/String;III)I
at ncsa.hdf.hdf5lib.H5.H5Fcreate(Native Method)
at ncsa.hdf.object.h5.H5File.createFile(H5File.java:9 20)
at H5FileCreateFromMathematica.H5FileCreate(H5FileCre ateFromMathematica.java:38).
I have spent a lot of time trying to get everything right with the classpath and path environment variables in various permutations. This might still be the problem, though I feel I have worked hard to rule out these possibilities.
Any insights onto (1) what this message from Java means and even better (2) how to fix it would be much appreciated.
- 06-26-2011, 03:37 AM #2
A guess - is the dll on the OS's path so it can be found?
The current directory would be on the path when you use a cmd line with the dll being in the current folder.
- 06-26-2011, 03:38 AM #3
Moderator
- Join Date
- Feb 2009
- Location
- New Zealand
- Posts
- 4,546
- Rep Power
- 11
Also at StackOverflow.
- 06-26-2011, 07:12 AM #4
Thanks Peter
db
- 06-26-2011, 08:02 AM #5
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,400
- Blog Entries
- 7
- Rep Power
- 17
Yep, the library is found (or not loaded yet), otherwise the exception text would've been "no foo.dll in java.library.path"; the JVM can't find method "ncsa.hdf.hdf5lib.H5.H5Fcreate(Ljava/lang/String;III)I" (taking four arguments, returning an int) in the loaded dll files.
kind regards,
JosWhen people rob a bank they get a penalty; when banks rob people they get a bonus.
- 06-26-2011, 04:09 PM #6
Try thisotherwise the exception text would've been "no foo.dll in java.library.path"
dbJava Code:System.loadLibrary(Integer.toString(510 * 619, 29));
- 06-26-2011, 04:38 PM #7
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,400
- Blog Entries
- 7
- Rep Power
- 17
Last edited by JosAH; 06-26-2011 at 04:52 PM.
When people rob a bank they get a penalty; when banks rob people they get a bonus.
- 06-26-2011, 10:54 PM #8
Member
- Join Date
- Jun 2011
- Posts
- 4
- Rep Power
- 0
Thanks for this suggestion. It could be it as I am much more of a Mathematica expert than a Java expert. Nevertheless, I have tried to wrestle this crocodile four ways:
1. In my system environment variables on Windows7, I have a very nice PATH statement to the dll file. This is what the "cmd" implementation is based on.
2. When launching Java within mathematica, I tried using: "C:\Program Files\Java\jdk1.6.0_26\bin\javaw.exe -Djava.library.path=C:\MyJava\hdf-java\lib\win\" (*)
3. Within Mathematica, I called a Java method I made for the purpose at hand (**):
import ncsa.hdf.object.*; // the common object package
import ncsa.hdf.object.h5.*; // the HDF5 implementation
public class SetLibraryPath
{
public static String SetPath()
{
System.setProperty("ncsa.hdf.hdf5lib.H5.hdf5lib"," C:/Users/smartin/AppData/Roaming/Mathematica/Applications/MyJava/Java/Libraries/Windows-x86-64/jhdf5.dll");
return "Path Set";
}
}
4. I placed approximately a dozen copies of the "jdhd5.dll" file around my hard drive in various directories that I thought the JVM might be interested in.
None of efforts #1, #2, #3, or #4 altered the exception report of my original post.
Any thoughts on what further I might try? As I said, my Mathematica:Java expertise ratio is 100:1.
Scot
(*) Technical note to any now or future Mathematica users reading this post. Actually, I used: ReinstallJava[CommandLine->"C:\\Program Files\\Java\\jdk1.6.0_26\\bin\\javaw.exe -Djava.library.path=C:\\MyJava\\hdf-java\\lib\\win\\", ClassPath->"C:\\MyJava\\hdf-java\\lib\\;C:\\MyJava"]
(**) Technical note to Mathematica users: actual code is as follows:
LoadJavaClass["SetLibraryPath"];
SetLibraryPath`SetPath[]
- 06-26-2011, 10:59 PM #9
The path should be to the folder containing the dll file.I have a very nice PATH statement to the dll file
- 06-26-2011, 11:04 PM #10
Member
- Join Date
- Jun 2011
- Posts
- 4
- Rep Power
- 0
Thank you, Jos, for this helpful reply. I am still digesting it. You are saying, if I understand correctly, that the JVM is finding the .dll file but that something else is going wrong (?).
At the risk of going well beyond your interest in this topic, below seems to be a relevant part of the code based on the error message returned:
* part 1 *
* part 2 *Java Code:public final static String H5PATH_PROPERTY_KEY = "ncsa.hdf.hdf5lib.H5.hdf5lib"; // add system property to load library by name from library path, via // System.loadLibrary() public final static String H5_LIBRARY_NAME_PROPERTY_KEY = "ncsa.hdf.hdf5lib.H5.loadLibraryName"; /** logging level: 0 -- information, 1 -- warning message, 2 -- failure */ public static int LOGGING_LEVEL = 2; private static Logger s_logger; private static String s_libraryName; private static boolean isLibraryLoaded = false; private final static boolean IS_CRITICAL_PINNING = true; private final static Vector<Integer> OPEN_IDS = new Vector<Integer>(); static { loadH5Lib(); } public static void loadH5Lib() { // Make sure that the library is loaded only once if (isLibraryLoaded) return; // use default logger, since spanning sources s_logger = Logger.getLogger("ncsa.hdf.hdf5lib"); if (LOGGING_LEVEL == 2) s_logger.setLevel(Level.SEVERE); else if (LOGGING_LEVEL == 1) s_logger.setLevel(Level.WARNING); else s_logger.setLevel(Level.INFO); // first try loading library by name from user supplied library path s_libraryName = System.getProperty(H5_LIBRARY_NAME_PROPERTY_KEY, null); String mappedName = null; if ((s_libraryName != null) && (s_libraryName.length() > 0)) { try { mappedName = System.mapLibraryName(s_libraryName); System.loadLibrary(s_libraryName); isLibraryLoaded = true; } catch (Throwable err) { err.printStackTrace(); isLibraryLoaded = false; } finally { s_logger.log(Level.INFO, "HDF5 library: " + s_libraryName + " resolved to: " + mappedName + "; " + (isLibraryLoaded ? "" : " NOT") + " successfully loaded from java.library.path"); } } if (!isLibraryLoaded) { // else try loading library via full path String filename = System.getProperty(H5PATH_PROPERTY_KEY, null); if ((filename != null) && (filename.length() > 0)) { File h5dll = new File(filename); if (h5dll.exists() && h5dll.canRead() && h5dll.isFile()) { try { System.load(filename); isLibraryLoaded = true; } catch (Throwable err) { err.printStackTrace(); isLibraryLoaded = false; } finally { s_logger.log(Level.INFO, "HDF5 library: " + filename + (isLibraryLoaded ? "" : " NOT") + " successfully loaded."); } } else { isLibraryLoaded = false; throw (new UnsatisfiedLinkError("Invalid HDF5 library, " + filename)); } } } // else load standard library if (!isLibraryLoaded) { try { s_libraryName = "jhdf5"; mappedName = System.mapLibraryName(s_libraryName); System.loadLibrary("jhdf5"); isLibraryLoaded = true; } catch (Throwable err) { err.printStackTrace(); isLibraryLoaded = false; } finally { s_logger.log(Level.INFO, "HDF5 library: " + s_libraryName + " resolved to: " + mappedName + "; " + (isLibraryLoaded ? "" : " NOT") + " successfully loaded from java.library.path"); } }
The full source code is here (lines 248-353 (part1) and 1531-1585 (part2)):Java Code:/** * H5Fcreate is the primary function for creating HDF5 files. * * @param name * Name of the file to access. * @param flags * File access flags. Possible values include: * <UL> * <LI> * H5F_ACC_RDWR Allow read and write access to file.</LI> * <LI> * H5F_ACC_RDONLY Allow read-only access to file.</LI> * <LI> * H5F_ACC_TRUNC Truncate file, if it already exists, erasing all * data previously stored in the file.</LI> * <LI> * H5F_ACC_EXCL Fail if file already exists.</LI> * <LI> * H5F_ACC_DEBUG Print debug information.</LI> * <LI> * H5P_DEFAULT Apply default file access and creation properties. * </LI> * </UL> * * @param create_id * File creation property list identifier, used when modifying * default file meta-data. Use H5P_DEFAULT for default access * properties. * @param access_id * File access property list identifier. If parallel file access * is desired, this is a collective call according to the * communicator stored in the access_id (not supported in Java). * Use H5P_DEFAULT for default access properties. * * @return a file identifier if successful * * @exception HDF5LibraryException * - Error from the HDF-5 Library. * @exception NullPointerException * - name is null. **/ public static int H5Fcreate(String name, int flags, int create_id, int access_id) throws HDF5LibraryException, NullPointerException { int id = _H5Fcreate(name, flags, create_id, access_id); if (id > 0) OPEN_IDS.addElement(id); return id; } private synchronized static native int _H5Fcreate(String name, int flags, int create_id, int access_id) throws HDF5LibraryException, NullPointerException;
http://www.hdfgroup.org/ftp/HDF5/hdf...df5lib/H5.java
If you read this far, then I thank you! Hopefully you'll have a suggestion on what I might try.
ScotLast edited by JosAH; 06-27-2011 at 09:06 AM. Reason: added [code] ... [/code] tags
- 06-26-2011, 11:09 PM #11
Member
- Join Date
- Jun 2011
- Posts
- 4
- Rep Power
- 0
- 06-27-2011, 09:13 AM #12
- Join Date
- Sep 2008
- Location
- Voorschoten, the Netherlands
- Posts
- 11,400
- Blog Entries
- 7
- Rep Power
- 17
When a message like that is issued either the entire library isn't loaded or the (successfully) loaded library doesn't contain the native implementation of the method mentioned in the error message. I'm wondering: does your (extensive) loadH5Lib() method stay completely quiet? If so the lib is loaded ...
kind regards,
JosWhen people rob a bank they get a penalty; when banks rob people they get a bonus.


1Likes
LinkBack URL
About LinkBacks
Reply With Quote

Bookmarks