Preparing JNA for use in Eclipse - java

Background:
I'm doing machine learning research, and want to use the FANN library to construct neural networks. The source code is written in C, but I need it wrapped so that I can use it with a lot of Java classes we've created.
Question:
The website provides a link to an already well received wrapper software called fannj. Its dependencies is the FANN library source code and JNA. I've never done wrapping before so JNA is brand new to me. The github homepage for the code mentions "you must set the jna.library.path system property to the path of the FANN Library". I'm currently in the process of trying to do this in Eclipse on Mac OS X. A friend of mine mentioned to me earlier that it means I have to pass the location of the FANN library as argument to the virtual machine, but he only showed me how to do this via the shell. I never actually ran this command from the shell, because I wasn't sure how it would conflict with whatever configurations I do in Eclipse later.
How do I set the jna.library.path in Eclipse? The JNA directory is huge, and I don't know where the actual executable is. My friend suggested I modify its run configuration through use of the argument tab, but like I said I don't actually know where the executable is. All I have is the large uncompressed jar file. How can I go about getting it set up in Eclipse?

You don't set in an IDE, just insert in some piece of code that is called BEFORE JNA is called, something like this:
System.setProperty("jna.library.path", "path you need");
Where System is java.lang.System. As for what path you need it must be the path that contains compiled dynamically linked FAAN library (a *dll).
Or just forget that alltogether and dump FAAN (*dlls, *so..) into Windows/system32 (or other appropriate folder on system you use) and these dll's will be on default search path.

Two allow Eclipse to use JNA, all you need to do is to put two jar files in Eclipse's Java Build Path, jna.jar and platform.jar. That's it.
To do this for an individual project, right click on the project in the Package Explorer, click Properties (at the bottom), click Java Build Path on the left, then the Add External Jar files. Browse to the directory with your JNA files and add those two files.

Related

Cross-platform Java with native libraries

I am trying to implement a wrapper for native libraries that will be consumed via JNI in a Java application. I want to make installation of the program be as simple as "Unzip this file and run".
I've worked through most of the wrapper so far, getting it to unzip the native libraries from inside the platform-specific JAR file and setting the -Djava.native.lib variable at runtime. I've hit one last roadblock due to unsatisfied link errors.
On Windows, the DLLs that I'm calling link against msvcr100.dll. While the DLLs that I'm calling into are getting picked up by java.native.lib, msvcr100.dll isn't. I don't want to have to require the user to install the C++ runtime before using our app, so we are packaging the DLL file right along side the other DLLs.
As far as I understand, to get things to work we need to put the folder that contains msvcr100.dll on the PATH. I tried using reflection to change the environment inside the application to add the unpack directory to the PATH environmental variable. After this was unsuccessful, I recalled that I was only modifying a copy of the environment.
Is there some way that I can fix the unsatisfied link error without requiring any additional system setup (installing the runtime, hand modification of PATH, etc)? I would think it is possible since I've encountered other pieces of software (SWT, JOGL) that package native libraries that don't exhibit this issue.

JNI to call .NET dll

I am trying to create a Java Application that will call C# dll through an intermediate Visula C++ dll, its all well and good when I try to run the .class file from cmd prompt or Eclipse IDE but the problem is in order to do it I need to place the C# dll in the same directory as the Java.exe or else there occurs an exception the the native call, thus making to impossible to build the Java Project, any idea as to how this can be done
There are other ways, without COM. You might find one preferable or need one if you can't change the .NET component to support COM clients.
When a process that loads the CLR, the assembly search paths are determined by the location of the process's main Win32 module. Assembly search paths are different than Win32 DLL search paths. In this case, it starts with the location of java.exe. As a result, the search paths include the Global Assembly Cache (GAC), the folder of java.exe, and subfolders listed as assembly probing paths in java.exe.config (if it exists).
See How the Runtime Locates Assemblies.
This leads to a few options:
Install the assembly in the GAC. (On an end-user machines an installer should be used but on a developer machine, you can use gacutil.)
Put the assembly in the java.exe folder. Or, conversely, put a copy of Java in your application folder.
Create a subfolder with write permissions for the assembly. Create or update a java.exe.config and list the subfolder as a probing path.
Create your own java.exe in C or C++ using the Java Invocation API. It's documented alongside JNI. You can name it whatever you wish since, after all, it is your application. (This what many Java-based applications do, even if they don't use .NET. For example, eclipse and LibreOffice.) The documentation gives a complete example in C. For a typical MSVC build, jni.h needs to on the project's include path, jvm.lib needs to be on the project's library path, and jvm.dll needs to be in the Win32 DLL search path.
Other alternatives:
The VC DLL can load the assembly explicitly from a path before the assembly is needed. See Assembly::LoadFile.
Load the assembly on demand after it's not found by the standard search. See AppDomain::AssemblyResolve Event (but note it's description is wrong: failure has not occurred until and if your custom resolver(s) fails).
You can enable and register your managed (.NET) dll with COM Interop.
See this link: http://support.microsoft.com/kb/828736

VLCJ setting custom library location at runtime

I have a Java program that uses vlcj to play videos and that packages the VLC libs in the jar. At runtime, the VLC libs are extracted to the user's home, let's say path A. The normal way to indicate this path to vlcj is through the jna method:
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "A");
This works under Windows and MacOSX but not Linux where it throws a UnsatisfiedLinkError.
After some trial and error, I found that the only to get this to work under linux was by using
export LD_LIBRARY_PATH=A
prior to execution and despite the JNA documentation, none of these worked in JVM settings:
-Djava.library.path=A
-Djna.library.path=A
-Djna.platform.library.path=A
My problem with using LD_LIBRARY_PATH is that it is not something I can set at runtime (can I?) which I need to do. Does anyone know of a way to get around this?
I never found an ideal solution to this myself, but this is what I found during my trials with my own vlcj projects.
If you build VLC yourself on Linux you will see these warnings:
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,-rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'
None of those things it suggests can you do from within your JVM, at least not without calling native code with privilege escalation.
So, in general what you are left with is: -Djna.library.path=LIBDIR should work; alternatively in code System.setProperty("jna.library.path", "LIBDIR"); should also work.
In fact I just tested that with my own native library that I happen to use in my own vlcj projects and both of those approaches worked just fine.
However, it seems it is not so easy with VLC itself, probably because of the way VLC loads its plugins.
In theory, if you structure your directories correctly, the plugins should get discovered automatically so you only need to point jna.library.path to the directory that contains the libvlc and libvlccore shared objects. In my build of VLC, the directory structure looks like this:
VLCDIR
VLCDIR/libvlc.so
VLCDIR/libvlc.so.5
VLCDIR/libvlc.so.5.4.0
VLCDIR/libvlccore.so
VLCDIR/libvlccore.so.7.0.0
VLCDIR/vlc/plugins
If this still fails then, again in theory, you can set the VLC_PLUGIN_PATH environment variable to point to the directory containing the VLC plugins. The problem is that this must be set for the native process, it will not work if you set it as a system property from inside your Java application.
I can only really suggest you generate a shell-script file that sets up the environment correctly when you install your application, or if you want to do it programmatically inside the JVM you could maybe have a bootstrap application that prepares the native environment and then kicks off a new Java process for your actual application - but it's messy to do things that way.
What I have also seen on Linux is that the library paths seem "baked in" to the ".so" files, and you can't just copy those files anywhere and still expect it to work. That is why you must use e.g. LD_LIBRARY_PATH or libtool or one of the other proposed solutions.
And this does not even touch on what you do with all the other libraries that VLC and its plugins may depend on at run-time - are you going to ship all those too?
My recommendation really is just to have the user install VLC first, or have your installer application install VLC first, by using the OS native package installation commands. Not ideal, but it works.

Java Working Directory

I'm pretty new to programming, so this should be an easy one. I'm switching from eclipse to netbeans and I am trying to add libjinput-osx.jnilib to my working directory. I have step by step instructions for eclipse, but not netbeans. I'm about 2.5 hours and 65 google searches in and I still cant find the answer to these two basic questions I have.
What exactly is a working directory in java?
How do you add a .jnilib file to your working directory in netbeans?
My end goal is to get an xbox controller to control a game of snake I wrote. I am trying to use JInput and this tutorial. In order to compile properly on OSX I need to put libjinput-osx.jnilib in the "working directory".
The "working directory" is the location where the application is working in...cryptic huh ;)
Typically it's the launch location for the app, although this can be modified through flags and other process.
In Netbeans, the working directory is typically the root directory of the project (which contains the src and nbproject folder), but this can be changed via the project properties.
One of the simplest ways to find the working directory at run time (this is useful for testing) is to do some thing like...
System.out.println(new File(".").getAbsolutePath());
There are two aspects to this question.
When you run a command from the command line, the "working directory" is the directory you were in when you ran the command. The instructions that you are reading say to put the native library there because Java's default search path for native library includes the current directory. Alternatively, you could add a -Djava.library.path=... option to the java command to set the search path explicitly.
When you run a command from within Eclipse ... or NetBeans ... the IDE's launcher will set the appropriate JVM parameters to include the project's native library directory on the search path. You need to put the library in THAT directory. This wiki page explains what you need to do for NetBeans.
It looks like what you're really trying to do is load a native library. Try this:
public class MainClass {
static {
System.loadLibrary( "Your_native_lib_file_name" ); // Note: do not include the file extension!
}
}
You might also try -Djava.library.path=/exact/path/to/dir/
Answer copied from here:
Java can't seem to find my native libraries

How to debug a java system.loadlibrary error in linux?

I have a Java program that is calling C code through JNI that I'm attempting to run on Linux. The external code consists of two .so files: one for the JNI bindings (built with swig) and the other with the actual functions. I have the two libraries in the same directory and LD_LIBRARY_PATH is set correctly. ldd reports no problems when running from the command line, but when I set the LD_LIBRARY_PATH to the same value in the "run configurations" dialog in the Eclipse editor and attempt to execute the program, it gets the following error:
java.lang.UnsatisfiedLinkError: [path to libraries]/[JNI binding library].so: [actual code library].so: cannot open shared object file: No such file or directory
This leads me to believe that the JNI wrapper library is loaded successfully, but there is a failure when that library attempts to load the library containing the actual code. Is there any way to debug this further?
I will further note that this problem is happening in the eclipse editor itself and that I haven't attempted to package the code into a jar and run it within a free-standing jvm instance.
I think the issue is with the call to System.loadLibrary(String) and using LD_LIBRARY_PATH. Using loadLibrary("foo") will look in your java.library.path for something named libfoo.so. If nothing named libfoo.so is found you will get this error.
Now if you just set up the LD_LIBRARY_PATH, the native symbols you want will automatically be picked up by the linker, so you don't need to set up -Djava.library.path.
In my experience with swig in the gdal project, this error is actually harmless and since the LD_LIBRARY_PATH is set up, this will work fine.
I would recommend using -Djava.library.path and calling loadLibrary explitly, the reason being that if you ever decide to deploy your app with webstart, you will explicitly need to call loadLibrary to get your native libs picked up.
When I use eclipse I follow the instructions that Daff gave where you edit the native library under the jar in the Libraries tab in the Build Path. Just to mention again, this just sets java.library.path under the covers.
It may be that you just have to find the right place on the run config dialog to put the -Djava.library.path=... option. Offhand I think you want -D defines in the "vm arguments" on the arguments tab, whereas if you want to define LD_LIBRARY_PATH that goes on the environment tab. Eclipse will merrily let you put things in places where they won't mean what you think they mean. Anyway, I've used libraries this way before and if I get a chance I will look up what I did and edit my answer here.
Another thing to try is to play with LD_DEBUG. You can set the environment variable LD_DEBUG to various things (try ALL), and then the linux loader will divulge all sorts of useful information about what an application is trying to load, where it's looking for things, etc. Of course, this pre-supposes you launch eclipse from a command line, so you can both set the env vars and see the loader diagnostics; but as far as the system is concerned, when you run your app from inside eclipse, your app is just something eclipse is doing, so any library loading behavior can be seen in this way.
You could try -Djava.library.path=actual.so in command line parameters perhaps?
On windows, I had similar problems with a 3rd party library, which used a JNI wrapper DLL for its DLLs. My project had the DLL in the lib directory so I added lib to the PATH (e.g. PATH=%PATH%;./lib environment variable and everything started working.
As far as I know the Eclipse doesn't use the LD_LIBRARY_PATH.
The easiest way to set up the right native library path is to go to
Project properties -> Java Build Path -> Libraries
Then expand either the JRE System Library entry or (if available) the
Jar File that uses you native Library,
choose "Native Library Location" then click "Edit..." and choose the folder your libraries are in. Actually it does set the -Djava.library.path variable so you have to include this in your command line if you start your program from outside eclipse.
Are there any other libraries that your two libraries depend on? If so, you need to make sure they are also accessible to the JVM.
Be aware, manually setting "-Djava.library.path" seems to erase the default library path.
So with the following code:
public class LibTest {
public static void main(String[] args) {
String property = System.getProperty("java.library.path");
StringTokenizer parser = new StringTokenizer(property, ":");
while (parser.hasMoreTokens()) {
System.err.println(parser.nextToken());
}
}
}
Launched from eclipse with Java 1.6.0_14 outputs:
/opt/java/jre/lib/i386/client
/opt/java/jre/lib/i386
/opt/java/jre/../lib/i386
/opt/java/jre/lib/i386/client
/opt/java/jre/lib/i386
/usr/lib/xulrunner-devel-1.9.0.11
/usr/lib/xulrunner-devel-1.9.0.11
/usr/java/packages/lib/i386
/lib
/usr/lib
But when I set the JVM arg "-Djava.library.path=/tmp/" I only get:
/tmp/
If you are manually setting java.library.path this may explain why ldd works from the command line but your .so does not from eclipse/java.
You can try not setting java.library.path and use System.load with the absolute path to your library instead of calling System.loadLibrary. This may allow the JVM to find your .so and still use the default path when searching for its dependencies.
Of course, if this is no use then you can also try turning on jni debug output with "-verbose:jni" on the command line. This may give you some clues to the problem.
Yes the LD_LIBRARY_PATH worked for me
Adding this answer may be it can be useful In AIX Machines we need to setup LIBPATH environment variable instead of LD_LIBRARY_PATH.

Categories

Resources