Loading native libraries in java - java

I have an eclipse project with two classes. The class "SomeClass1" has a native method:
SomeClass1
public class SomeClass1 {
static {
System.loadLibrary("libname"); // Load the native library.
}
public native void some_method(); // implemented in the library
// .... other non methods ....
}
The other class "SomeClass2" uses the native method of "SomeClass1". Like:
SomeClass2
public class SomeClass2{
public static void main(String[] args) {
SomeClass1 s = new SomeClass1();
s.some_method();
}
// ....other methods....
}
However when it calls that method it throws an error like this:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no libname in java.library.path
....
at java.lang.System.loadLibrary(Unknown Source)
at x.x.x.SomeClass1.<clinit>(SomeClass1.java:128)
at SomeClass2.main(SomeClass2.java:10)
I think the error has something to do with java not knowing where to look for the native library.
Question1
When I use: -Djava.library.path="C:\Users.....\libfolder\" as run argument in eclipse and print the value of: System.getProperty("java.library.path"); I see alot of directories printed but not the directory that I specified in the argument. What am I doing wrong?
Question2
When I do: System.loadLibrary("name"); do I need to call the library "name.so" or "libname.so"?
Question3
If the library would be found but was a 64 bit library while the platform it is loaded on is 32 bit, would it also give a unsatisfiedLinkError or would a different error be given?
Question4
Can I specify the path to the library relative to the projects folder or relative to the file in which the library is loaded?
Hope you are able to answer (some of) my questions.
Grtz Stefan

Question 1:
You should not add this as a run argument, but as a VM argument. It's not an argument for your program, but for the JVM.
Question 2:
(Also #IanRoberts ) : The System.loadLibrary(name) call will automatically derive the name of the actual library from the given name. That means that it will append ".dll" on windows, and use "lib" + name + ".so" on linux. Otherwise, loading a native lib would not be possible in a platform-independent way!
Question 3:
In general, the UnsatsfiedLinkError is distressingly common. It's in fact true to say: The UnsatisfiedLinkError does not tell you more than "Something is wrong". You can only hope for the actual error message to be more descriptive, and this would (fortunately) be the case if you had a 32/64bit mismatch - at least on windows:
Trying to load a 32bit lib on a 64bit system will cause the message: "Can't load IA 32-bit .dll on a AMD 64-bit platform"
Trying to load a 64bit lib on a 32bit system will cause the message: "... is not a valid Win32 application"
(I'm not sure about the message for other operating systems, though, but your message indicates that the library is just not found, and not that there's a problem with the library itself)
(Question 4: I'm rather sure that this is possible, but not absolutely sure (and can't try it out) at the moment. In general, the library must be in a path that is visible via the PATH environment variable, or via the java.library.path. In doubt, it should always work then the native libs are in the same directory as where you are starting your program from)

Related

Using jni4net to use Native DLL function in java and getting System.BadImageFormatException

I am using jni4net to use the DLL function in Java.
Using jni4net-0.8.6.0-bin I compile using the command:
.\proxygen.exe "D:\sampledlls\sample_interface.dll" -wd "D:\hope"
On executing this command , getting the following error:
System.BadImageFormatException: Could not load file or assembly 'file:///D:\sampledlls\sampledll.dll' or one of its dependencies. The module was expected to contain an assembly manifest.
I also used JNA library to use the DLL function in java. But in that as well I am getting the following error:
java.lang.UnsatisfiedLinkError: Unable to load library 'sampledll': The specified module could not be found.
Here is my code for JNA:
public class hellodll {
public interface dcmInterfaceDLL extends Library {
public void DCM_InitializeFields();
}
public static void main(String[] args) {
System.out.println(System.getProperty("java.library.path"));
System.setProperty("jna.library.path",
"C:\Users\320035705\Downloads\JNAHelloWorldMWrobel\JNAHelloWorldMWrobel\sampledlls");
dcmInterfaceDLL sdll = (dcmInterfaceDLL)
Native.loadLibrary("sample_interface", dcmInterfaceDLL.class);
System.loadLibrary("sample_interface");
sdll.DCM_InitializeFields();
}
}
This is a native.dll.
How can I load my DLL?
For the jni4net version, it properly found the dll but it is in the wrong format. It is possible that you are using a 32-bit JVM with a 64-bit DLL, or vice versa. You might try adding /32BIT+ /force switches to the proxygen command line.
There may be other problems with the DLL as the error message mentions its dependencies. Your comments indicate an error message associated with Visual C++ runtime package.
For the JNA library loading, you are not finding the DLL due to improper escaping of backslashes.
In Java (and many other languages) the backslash (\) is an escape character. When used in a String it has special meaning, such as (\n) for a newline.
In your String representing the path, you have not escaped the backslashes, so the String "C:\Users\320035705\Downloads\JNAHelloWorldMWrobel\JNAHelloWorldMWrobel\sampledlls" ends up being interpreted as "C:Users320035705DownloadsJNAHelloWorldMWrobelJNAHelloWorldMWrobelsampledlls".
Use two backslashes (\\) to represent a single backslash in a Java String. If you specify your path like this, it should work for JNA:
System.setProperty("jna.library.path",
"C:\\Users\\320035705\\Downloads\\JNAHelloWorldMWrobel\\JNAHelloWorldMWrobel\\sampledlls");
However, if there are issues where the DLL requires another dependency, this could fail for the same reason.

Ensuring files are available to the JVM

I'm trying to install TensorFlow for Java on Windows 10 using this Article
. I followed the steps carefully but the windows commands didn't work with me so I decided to do it manually.
The first command is to make the .jar part of the classpath and I did it manually
but the second step was to ensure that the following two files are available to the JVM: the .jar file and the extracted JNI library
but I don't know how to do that manually
The code:
package securityapplication;
import org.tensorflow.TensorFlow;
import org.tensorflow.Graph;
import org.tensorflow.Session;
import org.tensorflow.Tensor;
public class SecurityApplication {
public static void main(String[] args) throws Exception {
try (Graph g = new Graph()) {
final String value = "Hello from " + TensorFlow.version();
// Construct the computation graph with a single operation, a constant
// named "MyConst" with a value "value".
try (Tensor t = Tensor.create(value.getBytes("UTF-8"))) {
// The Java API doesn't yet include convenience functions for adding operations.
g.opBuilder("Const", "MyConst").setAttr("dtype", t.dataType()).setAttr("value", t).build();
}
// Execute the "MyConst" operation in a Session.
try (Session s = new Session(g);
Tensor output = s.runner().fetch("MyConst").run().get(0)) {
System.out.println(new String(output.bytesValue(), "UTF-8"));
}
}
}
}
could someone help? cuz my program that uses TensorFlow still have the following error
The text in the image is :
Exception in thread "main" java.lang.UnsatisfiedLinkError: Cannot find TensorFlow native library for OS: windows, architecture: x86. See https://github.com/tensorflow/tensorflow/tree/master/tensorflow/java/README.md for possible solutions (such as building the library from source). Additional information on attempts to find the native library can be obtained by adding org.tensorflow.NativeLibrary.DEBUG=1 to the system properties of the JVM.
at org.tensorflow.NativeLibrary.load(NativeLibrary.java:66)
at org.tensorflow.NativeLibrary.load(NativeLibrary.java:66)
at org.tensorflow.TensorFlow.init(TensorFlow.java:36)
at org.tensorflow.TensorFlow.<clinit>(TensorFlow.java:40)
at org.tensorflow.Graph.<clinit>(Graph.java:194)
at securityapplication.SecurityApplication.main(SecurityApplication.java:15) Java Result: 1 BUILD SUCCESSFUL (total time: 4 seconds)
The result after running the first command in cmd:
The result after running the second command in Windows PowerShell:
Any suggestions?!
Thank you
The first command failure (javac) suggests that the javac command is not in your PATH environment variables. See for example, this StackOverflow question
For the second command failure, I believe the space after -D is what is causing you trouble as Holger suggested.
IDEs like Eclipse and others also provide a means to set the java.library.path property for the JVM (see this StackOverflow answer for example).
Background: TensorFlow for Java consists of a Java library (packaged in a .jar file) and a native library (.dll on Windows, distributed in a .zip file). You need to ensure that the .jar file is in the classpath and the directory containing the .dll is in included in the java.library.path of the JVM when executing a program.
Hope that helps.

Is it possible to prepend bootclasspath for Dalvik VM on Android?

I'm experimenting with -Xbootclasspath in Java just for fun, and have added a test method int java.lang.Object#id(), just an instance-like identityHashCode method shortcut:
package java.lang;
public class Object {
public final int id() {
return System.identityHashCode(this);
}
// the original code goes here
}
The code above is compiled into a single-class JAR file, and the code below is compiled and dependent on the patch JAR file, thus the following code is legal:
public static void main(final String... args) {
System.out.println(new Object().id());
}
Running the sample application is quite easy prepending the bootstrap classes:
$ java -Xbootclasspath/p:patch.jar -cp app.jar test.Application
366712642
Works fine. Now, I wondering if it's possible to do the same trick on Android. So, the closest equivalent, I think, should be (from adb shell):
$ dalvikvm -Xbootclasspath:patch.jar -cp app.jar test.Application
java.lang.NoSuchMethodError: No virtual method id()I in class Ljava/lang/Object; or its super classes (declaration of 'java.lang.Object' appears in /syework/core-libart.jar)
at test.Application.main(Application.java:11)
Looks like prepending, but not working since it's saying that the java.lang.Object class is already defined in another location (probably the real path is /system/framework/core-libart.jar, at least it says similar, but that JAR is quite different -- then how after all?). I also saw a few examples with the $BOOTCLASSPATH variable, but none of them works for me for some reason.
Is it possible to run dalvikvm overriding the bootclass path somehow and where are the core classes are loaded from?
EDIT 1:
It probably would work, but Android Dalvik VM is really dependent on the zygote that all new Dalvik VM processes are forked from, thus the zygote does not run with an alternative boot classpath. At least, this is what I understood from this question: How to pass dalvik command line parameters through .apk?

AIX: "java.lang.UnsatisfiedLinkError" but the library exists

I'm using JNI to call a shared library named "libmy_jni.so" from my java code. Those are working good without any problem in other OS's but in AIX, I see the following error. I've checked that the LIBPATH and LD_LIBRARY_PATH(in case) are set correctly and matched x86 module with 32bit java(and x64 with 64bit java).
Exception in thread "Thread-1" java.lang.UnsatisfiedLinkError: my_jni (No such file or directory)
The java code loading the library is,
File sofile = new File("libmy_jni.so");
if(!sofile.exists())
{
System.out.println("can't find the moudle.");
System.exit(1);
}
System.loadLibrary("my_jni");
As I know, the most cases causing the error above are incorrect library path or unmatched 32/64bit architecture. But in my case I don't see what could be the reason.
>>file libmy_jni.so
libmy_jni.so: 64-bit XCOFF executable or object module not stripped

Calling Fortran DLL in Netbeans IDE 8.0.2 Java

I have an issue. I got a DLL written in Fortran. And I want to call this DLL in Java.
Everything is working fine for other DLLs when I try to call them from a test-Java program. The DLL is existing. Unfortunately, regardless whether I use System.load and mention the whole path or use the loadLibrary method and mention only the DLL's name the same error message is returned:
java.lang.UnsatisfiedLinkError: C:\Windows\System32\MYDLL.dll: Not enough storage is available to process this command
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1929)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1847)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1119)
at OnlyForTesting.(OnlyForTesting.java:11)
Exception in thread "main" Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)
Here is my code:
public class TryToCallDLL {
private native void method();
public static void main(String[] args){
System.out.println("Test\n");
new TryToCallDLL().method();
}
static{
System.load("C:\\Users\\xxx\\Documents\\NetBeansProjects\\JNItutorial\\src\\TryToCallDLL\\Debug\\MYDLL.dll");
}
}
I was searching for anything helpful related to similar errors but nothing was working. There was though one comment stating it could be related to a limited heap storage.
I want to emphasize that this DLL's purpose is calculating using a lot of data.
I also want to add that the DLL is a 32bit version. My PC is 64 bit, I have two Netbeans version (32bit and 64bit), but running the Java program with the 32bit version.
Any suggestions are welcomed. Thank you in advance!
EDIT:
I increased the heap in the settings: -Xmx1024m
The DLL itself has a size of 1,955 KB.
Still the DLL cannot be loaded.

Categories

Resources