Adding native library to java project results with unsatisfied link - java

I am constantly running into error when i try to add .dll to build path of java project.
I have created .dll file with mingw64 using the following command:
gcc -o ctest.dll -shared -I"C:\Program Files\Java\jdk1.8.0_45\include"
-I"C:\Program Files\Java\jdk1.8.0_45\include\win32" ctest.c -LC -m64
Created .dll file is in the same directory as the main class using the dll.
bin/com/jni
I have tried to include .ddl to java project from Eclipse by doing the following steps:
BuildPath -> Native library location -> path_to_directory_with_.dll
This results with:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.jni.HelloWorld.helloFromC()V
at com.jni.HelloWorld.helloFromC(Native Method)
at com.jni.HelloWorld.main(HelloWorld.java:14)
As the above didn't work, i tried to run the application from command line:
C:\Users\Z003DP9F\java-8 workspace\workspace\JNI_Test\bin>java
-Djava.library.path="C:\Users\Z003DP9F\java-8 workspace\workspace\JNI_Test\bin\com\jni"
com.jni.HelloWorld
and the same error, although on line 12 rather than 14 like in example above.
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.jni.HelloWorld.helloFromC()V
at com.jni.HelloWorld.helloFromC(Native Method)
at com.jni.HelloWorld.main(HelloWorld.java:12)
c file:
#include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_helloFromC
(JNIEnv * env, jobject jobj)
{
printf("Hello from C!\n");
}
Java main class:
package com.jni;
public class HelloWorld {
native void helloFromC(); /* (1) */
static {
System.loadLibrary("ctest"); /* (2) */
}
static public void main(String argv[]) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.helloFromC(); /* (3) */
}
}
The example i have been trying to setup was taken form:
jni

The signature is wrong; you can use javah to get the signature for you, but in your case it is simply
JNIEXPORT void JNICALL Java_com_jni_HelloWorld_helloFromC(JNIEnv * env, jobject thiz)

Related

What "symbol lookup error: /usr/lib/libpylontesting.so: undefined symbol: _ZN5Pylon15PylonInitializeEv" means?

I am trying to use some c++'s libraries in Java (IDE is NetBeans). I have created the shared library, which is called "pylontesting.so". The following code is what it was used to create it:
g++ -fPIC -lbxapi -lbxapi-6.3.0 -lGCBase_gcc_v3_1_Basler_pylon -lGenApi_gcc_v3_1_Basler_pylon -lgxapi -lgxapi-6.3.0 -llog4cpp_gcc_v3_1_Basler_pylon -lLog_gcc_v3_1_Basler_pylon -lMathParser_gcc_v3_1_Basler_pylon -lNodeMapData_gcc_v3_1_Basler_pylon -lpylonbase -lpylonbase-6.3.0 -lpylonc -lpylonc-6.3.0 -lpylon_TL_bcon -lpylon_TL_bcon-6.3.0 -lpylon_TL_camemu -lpylon_TL_camemu-6.3.0 -lpylon_TL_gige -lpylon_TL_gige-6.3.0 -lpylon_TL_gtc -lpylon_TL_gtc-6.3.0 -lpylon_TL_usb -lpylon_TL_usb-6.3.0 -lpylonutility -lpylonutility-6.3.0 -luxapi -luxapi-6.3.0 -lXmlParser_gcc_v3_1_Basler_pylon -L/opt/pylon/lib -I/opt/pylon/include -I/home/fra/NetBeansProjects/TestPylon/src/main/java/Pylon -I/lib/jvm/java-1.8.0-openjdk-amd64/include -I/lib/jvm/java-1.8.0-openjdk-amd64/include/linux -shared -o libpylontesting.so Pylon_NativeTest.cpp
This might look a mess, but basically I'm linking every libraries I need through the command "-l" and tell the linker where the libraries are using "-L" and then using "-I" for the headers into the c++ code. The c++ code that I'm using is the following:
#include <jni.h>
#include <stdio.h>
#include "Pylon_NativeTest.h"
#include <pylon/PylonIncludes.h>
#ifdef PYLON_WIN_BUILD
# include <pylon/PylonGUI.h>
#endif
using namespace Pylon;
JNIEXPORT void JNICALL Java_Pylon_NativeTest_Initialize (JNIEnv *, jobject){
PylonInitialize();
}
Its purpose is to export this simple library function called "PylonInitialize()". Then, I also have created my java file:
package Pylon;
/**
*
* #author
*/
public class NativeTest {
static {
System.loadLibrary("pylontesting");
}
private native void Initialize();
public static void main(String args[]){
new NativeTest().Initialize();
}
}
Which should call the function "PylonInitialize()" from the shared library created and called "pylontesting". But when I run the java main, it throws me the error:
usr/lib/jvm/java-11-openjdk-amd64/bin/java: symbol lookup error: /usr/lib/libpylontesting.so: undefined symbol: _ZN5Pylon15PylonInitializeEv
Command execution failed.
I'm using Maven as a compiler, and working under Ubuntu 21.10. Any ideas?

JVM exits without any error messages when loading compiled DLL

I'm trying to call a c function from Java.
When loading the library (in Test.java) 2 things happen randomly:
"Load Lib" gets printed, and the jvm just exits without any errors
"Load Lib" gets printed, and the jvm gets stuck in a loop
The weird thing is that 'sometimes' "Lib loaded" gets printed too. Which means the library got loaded...
My question is that how can I fix this? The real problem is that I don't know what I'm doing wrong.
Dll compilation steps:
gcc -fpic -I "C:\Program Files\Java\jdk-15\include" -I "C:\Program Files\Java\jdk-15\include\win32" -c BindLib.c BindLib.h
gcc -fpic -s -shared -o BindLib.dll BindLib.o
System info:
Windows 10 64 bit, version 1909
Java 15
Main file:
package degubi;
public final class Main {
public static void main(String[] args) {
Test.enable();
}
}
Library file:
package degubi;
public class Test {
static {
System.out.println("Load lib");
System.loadLibrary("BindLib");
System.out.println("Lib loaded");
}
public static native void enable();
}
Source file:
#include "windows.h"
#include "BindLib.h"
JNIEXPORT void JNICALL Java_degubi_Test_enable(JNIEnv* env, jclass clazz) {
}
Header file:
#define __int64 long long
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class degubi_Test */
#ifndef _Included_degubi_Test
#define _Included_degubi_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: degubi_Test
* Method: enable
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_degubi_Test_enable(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
Which shell and C compiler were you using?
The problem might come from the incompatible between C compiler & the shell environment.
For example, if you use Cygwin compiler to compile the DLL, then execute the binary on Windows CMD, the program might not work (dependencies on cygwin.dll).
I ended up creating a project in Visual Studio and building it from there... worked perfectly. Still don't know what caused the issue.

How to resolve UnsatisfiedLinkError when using JNI with packages?

Firstly, my example has the following directory structure:
Sample.c
lib/
mypackage/
--Sample.java
Sample.java in mypackage looks like this:
package mypackage;
public class Sample {
public static native int sampleMethod(int x);
public static void main(String[] args) {
System.loadLibrary("Sample");
System.out.println("sampleMethod result: " + sampleMethod(5));
}
}
I run javac mypackage/Sample.java to compile the java file and javah mypackage.Sample to generate the JNI headers. Then I compile the library using the following command:
clang -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" -o lib/libSample.so -shared Sample.c
At this point the directory structure looks like this:
Sample.c
mypackage_Sample.h
lib/
--libSample.so
mypackage/
--Sample.java
--Sample.class
Now when I try to run the example using java -Djava.library.path=./lib/ mypackage.Sample I get the following error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no Sample in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at mypackage.Sample.main(Sample.java:7)
I tried specifying the full path to lib/, but I get the same error.
I am not sure if the code for the header and the implementation matter, but I will post them anyway.
mypackage_Sample.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class mypackage_Sample */
#ifndef _Included_mypackage_Sample
#define _Included_mypackage_Sample
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: mypackage_Sample
* Method: sampleMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_mypackage_Sample_sampleMethod
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
Sample.c:
#include "mypackage_Sample.h"
#include <stdio.h>
JNIEXPORT jint JNICALL Java_mypackage_Sample_sampleMethod
(JNIEnv * env, jclass obj, jint num) {
return num * num;
}
I run this on OS X Yosemite 10.10.5 using clang 7.0.2 and java 1.8.0_101.
It looks like you have the wrong name from your library file (libSample.so).
If you use:
System.loadLibrary("Sample");
The JVM will map this name to a platform specific file name to try and load. On Linux that is libSample.so, on Windows that is Sample.dll, but on OS X it's something else.
You can find out which name your library file should have by looking at the output of:
System.mapLibraryName("Sample");
Called on the target platform.
After that, you can use that as the name of your library file.

JNI UnsatisfiedLinkError without wrong method names and with library path specified

I'm trying to work build my very first JNI application, following this tutorial: https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
Problem Summary: While running my application, I get an java.lang.UnsatisfiedLinkError error.
First I wrote the Class HelloJNI.java:
public class HelloJNI {
static {
System.loadLibrary("hello"); // Load native library at runtime
// hello.dll (Windows) or libhello.so (Unixes)
}
// Declare a native method sayHello() that receives nothing and returns void
private native void sayHello();
// Test Driver
public static void main(String[] args) {
new HelloJNI().sayHello(); // invoke the native method
}
}
This class I compiled with:
javac HelloJNI.java
Next I ran javah HelloJNI
This produced the following file HelloJNI.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */
#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Next I implemented HelloJNI.c:
#include <jni.h>
#include <stdio.h>
#include "HelloJNI.h"
// Implementation of native method sayHello() of HelloJNI class
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) {
printf("Hello World!\n");
return;
}
Finally I compiled the c class:
gcc -I"/usr/lib/jvm/java-8-oracle/include" -I"/usr/lib/jvm/java-8-oracle/include/linux" -c -Wall -Werror -fpic HelloJNI.c
gcc -shared -o hello.so HelloJNI.o
This produces the files hello.so and HelloJNI.o. Next I try to run the code:
java -Djava.library.path=. HelloJNI
This produces the error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1864)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at HelloJNI.(HelloJNI.java:3)
This seems to be the most common JNI error on the internet... My method names seem to be correct. I also ran:
nm hello.so | grep say
This gives me: 00000000000006b0 T Java_HelloJNI_sayHello which seems to be correct, i.e. the compiler didn't add additional characters. I simply ran out of ideas of things I could try. Any suggestions?
My OS: Linux Mint 13, GCC version 4.7.3, java version 1.8.0_60
==========UPDATE===============
When I replace System.loadLibrary("hello"); by System.load("/usr0/home/jkinable/workspace/javaIDEA/jnitest/hello.so"); my HelloWorld example works! However, I don't want to use an absolute path so I'm still looking for a way to use System.loadLibrary("hello"); instead? Any suggestions? I've also tried running on a different linux system, but I get the same issue.
It turns out that the problem is due to some naming convention on unix/linux platforms! When using:
System.loadLibrary("hello");
the file should not be named hello.so! Instead, the name should be libhello.so. On Windows, use hello.dll. I'm surprised that this issue is not mentioned in IBM's JNI tutorial: http://www.ibm.com/developerworks/java/tutorials/j-jni/j-jni.html
I'm not sure what the rationality behind this issue is. Why would you load a library "hello" which should be named libhello.so on your filesystem (instead of hello.so)?

java c++ jni unsatisfied link error

I'm quite a newbie to Java JNI. I tried a helloCPP program but ran into problems. here's my code :
helloCPP.java;
public class helloCPP {
public native void hellocpp ();
static {
System.loadLibrary("helloCPP");
}
public static void main (String [] args) {
helloCPP hcpp=new helloCPP ();
hcpp.hellocpp ();
System.exit (0);
}
}
Then here's my hellocpp.cpp out of which I made helloCPP.dll ;
#include <iostream>
#include "helloCPP.h"
using namespace std ;
JNIEXPORT void JNICALL Java_helloCPP_hellocpp. (JNIEnv *env, jobject obj) {
cout <<"hello java, I'm c++\n";
}
int main (){};
I successfully built the helloCPP.dll. But when I try to run java helloCPP, I get this error:
Exception in thread "main"
java.lang.UnsatisfiedLinkError: helloCPP.hellocpp () V
at helloCPP.hellocpp(Native Method)
at helloCPP.main (helloCPP.java :8)
I'm doing all these stuff on a Windows 8 x86 operating system.
These are the commands I wrote:
javac helloCPP.java
javah helloCPP
g++ -c hellocpp.cpp
g++ -o helloCPP.dll hellocpp.cpp
This one generated the error:
java HelloCPP
Thanks in advance.
Most likely, the Java run-time cannot locate the DLL file. You have run the Java application with additional arguments (assuming the DLL file is in the current directory):
java -Djava.library.path=. HelloCPP
Update:
EJP has a good point. I think your link command isn't correct. The second g++ command should be something like:
g++ -o helloCPP.dll -shared hellocpp.o
There are two changes: hellocpp.o instead of hellocpp.cpp and more importantly the option -shared to indicate that you want to create a shared library and not an executable.
The exact options depend on your platform. As you haven't specified it, I can't tell you for sure.

Categories