I have successfully called a method contained in a dll from a Java program using JNI. This is what i do:
public class MyClass {
static {
System.load("C:/Users/pabloruiz/library.dll");
System.loadLibrary("library"); // This works too if the dll is in the Java Build Path
}
public native void foo();
public static void main(String[] args) {
new MyClass().foo(); // invoke the native method
}
}
Now I'm trying to do the same but in a web app with Tomcat. I have tried using absolute paths and relative paths, placing the dll in WEB-INF/lib, selecting it in Properties->Java Build Path but it doesn't work. By the way, I'm working on Eclipse.
This is the error I get:
java.lang.UnsatisfiedLinkError: com.example.MyClass.foo()
EDIT:
Apparently, it founds the dll because if I change the name to something that doesn't exist I get an error telling me that the dll couldn't be found. From what I understand it can't find the method foo() inside the dll, which is weird because, as I said above, that same dll works from a simple java program (not a web app).
Related
I created a simple java class which gets the name of the operating system. I also created a batch file to run the java class with the bundled JAVA 7. It seemed to work fine in my system. But when I copied this file and ran the script in another system it threw Error: Could not find or load main class OSNameGenerator .
At first I thought This may have to do something with the script and that it is not able to find the bundled java due to some issues in path. But even simply running java file only from the cmd also is not working.
I know this feels is so simple yet I'm not able to find what is creating the issue here.
Here is my java class
public class OSNameGenerator{
public static void main(String[] args){
System.out.println(System.getProperty("os.name"));
}
}
and This my batch script
"%~dp0\jre\bin\java.exe" OSNameGenerator
pause
And this is my file structure
Please help me to find out what is wrong with this.
This seems to be an issue with classpath.
I fixed it by changing the classopath to current directory using (.) operator in my scrpit.
Here is my updated script
.\jre\bin\java.exe -cp . OSNameGenerator
pause
I am trying to write a simple servlet which just calls a native function.
First I tried to load the shared object in the servlet but then i got an "UnsatisfiedLinkError" because the library was already loaded in the JVM. After searching for this problem I found this tomcat documentation.
It basically says that I must write a loader which gets executed when the server starts up. So I wrote the following class:
class MyLibLoader
{
static
{
System.loadLibrary("foo");
}
native void doFoo();
public static void main(String[] args)
{
System.out.println("Lib loaded");
}
}
compiled it into a .class file and put it in the "$CATALINA_HOME/shared/lib/" folder, edited the property "shared.loader" in the "catalina.properties" file to the following:
shared.loader="${catalina.home}/shared/lib"
after restarting the tomcat without errors i get the following Exception in the servlet:
java.lang.UnsatisfiedLinkError
Which means, by my understanding, that the JNI library is not loaded. I tried to change the library name to a name that definitely does not exist and there you go: I can restart the tomcat without errors that the library is not found. I also tried to put the loader in a .jar file an change the property to:
shared.loader="${catalina.home}/shared/lib/*.jar"
It didn't work too.
Based on this I assume that the tomcat just ignores the "shared.loader" property.
We are trying to develop a Java application that loads a DLL (written in C++) and uses its functions.
When opening this DLL in "DLL Export Viewer" we can see the full signature of the functions exported, unlike any other DLL we load into the viewer:
Exported view of the DLL that doesn't work
We have tried to create some sample DLLs and load them to Java, and we were successful. The visibile difference was that when we loaded these DLLs we created into "DLL Export Viewer", we saw the functions without full signatures (only names):
DLL We created, works from Java
The code we use to load the DLL from Java is using JNA, and looks like this:
Declaring an interface that mathces the DLL functions:
public interface Ariel extends Library {
Ariel INSTANCE = (Ariel) Native.loadLibrary("ariel", Ariel.class);
void _ZN5ArielC1Ev();
int _ZN5Ariel8getArielEv();
}
Loading it and calling its functions:
public static void main(String[] args) {
Ariel ariel = Ariel.INSTANCE;
ariel._ZN5ArielC1Ev();
System.out.println("done");
}
Only when trying to load the DLL shown in the first image, we can't call any function and we always get the following error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'resetScale': The specified procedure could not be found.
at com.sun.jna.Function.<init>(Function.java:208)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:536)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:513)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:499)
at com.sun.jna.Library$Handler.invoke(Library.java:199)
at com.sun.proxy.$Proxy0.resetScale(Unknown Source)
at Bolet.main(Bolet.java:6)
Your DLL is exporting C++-mangled names. The DLL export is un-mangling them for you. If you examine the DLL with a different viewer, you should see the raw names instead.
If you want to export the names in a non-mangled manner, you need to use the extern "C" decorator on a given function declaration. This generally will only work for static methods (not class methods).
However, this is only part of your problem. If you want to directly map Java classes onto C++ classes, you'll need to use something like SWIG and compile some native glue code.
I'm a newbie to JNI, so I was trying this introduction to JNI tutorial earlier that just calls native to print Hello World! Everything went fine until the point that I wanted to run the java file, at which I keep getting the error: Exception in thread "main": java.lang.UnsatisfiedLinkError: no hello library found in java.library.path. I have googled the error and looked at a lot of peoples' suggestions, but none worked for me unfortunately! I have tried the following:
Running with command: java -Djava.library.path = "Path to library" HelloWorld
setting the LD_LIBRARY_PATH to my .so path
Everyone else had their issues resolved after doing one of the two above, but not me!
Here is the Java Code:
public class HelloWorld {
static {
System.loadLibrary("hello");
}
private native void printHelloWorld();
public static void main(String[] args) {
new HelloWorld().printHelloWorld();
}
}
And code for native is as follows:
void JNICALL Java_printHelloWorld(JNIEnv *env, jobject obj) {
printf("HelloWorld!");
}
EDIT: I even tried copying the library to the actually directory of java.library.path, but it's still giving me the same error!
What is your library called? If your paths are correct, your library name is probably wrong. If the library you are loading is called hello, on Windows the file needs to be called hello.dll, on every other SO you also need to prepend the lib prefix:
on OS X (Java < 1.7) libhello.jnilib
on OS X (Java >= 1.7) libhello.dylib
on just about everything else will be libhello.so.
Notice that the Windows dll file is the only file name without the "lib" prefix and that the "lib" prefix is not used when calling System.loadLibrary("hello").
If you are still experiencing a problem loading the lib, try System.load("/path/to/my/libhello.so") to try and load the library directly.
You can always check the file the system will look for by running
System.mapLibraryName(libName)
#Alex Barker
The version
System.load("/path/to/my/libhello.so")
does not resolve dependencies. If there are dependencies upon other user-defined libraries, they need to be loaded before.
I am working on an eclipse plugin development. It needs to launch system broswer and open a link. In Swing/SWT, I can do it like this:
java.net.URI uri = new java.net.URI("http://www.google.com");
java.awt.Desktop.getDesktop().browse(uri);
And in fact, this code also works in Eclipse plug-in. But I am wondering if eclipse has its own way to do this? Using AWT in eclipse seems some kind of weird...
Equivalent of java.awt.Desktop.getDesktop().browse(uri) is this Program.launch("http://www.google.com");
import org.eclipse.swt.program.Program;
public class del
{
public static void main(String[] args)
{
Program.launch("http://www.google.com");
}
}
The javadoc says:
Launches the operating system
executable associated with the file or
URL (http:// or https://). If the file
is an executable then the executable
is launched. Note that a Display must
already exist to guarantee that this
method returns an appropriate result.