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.
Related
I am quite new to JNI. Now I have a Question that, I have my own simple library in C. i have created both .so and .a library for my c library.
Generated libmymath.so Via following Command
gcc -shared -fPIC -o libmymath.so addnsub.o mulndiv.o
JNI.java
public class JNIPart
{
public native int addJNI(int a, int b);
public static void main(String args[])
{
JNIPart ja = new JNIPart();
int answer = ja.addJNI(10, 20);
System.out.println("Answer = "+ answer);
}
static
{
System.loadLibrary("mymath");
}
}
JNI.c
#include "JNIPart.h"
#include "stdio.h"
JNIEXPORT jint JNICALL Java_JNIPart_addJNI(JNIEnv *env, jobject thisObj, jint a, jint b)
{
return add(a, b);
}
JNI.h
#include "jni.h"
#include "addnsub.h"
#include "mulndiv.h"
JNIEXPORT jint JNICALL Java_JNIPart_addJNI(JNIEnv *env, jobject thisObj, jint a, jint b);
Note :- Function add() is part of my library.
Now When i am trying to compile JNI.c, It Works Fine with Following Command
gcc -c JNI.c -I="/home/axit/jdk1.7.0_67/include/"
Path of JDK include is for jni.h
Then I am Trying to Create the Shared Library Which should go to the System.loadLibrary() of Java
gcc -shared -fPIC -o libJNI JNI.o
As Mentioned earlier that, libJNI library will be go to the System.loadLibrary() of JNI.java
Question is :-
1) My libJNI Library Should Contain Both my own libmymath.so and JNI.o. Am i Right ?
2) When I am Trying to Generate the .so which is Combination of libmymath.so and JNI.o. It is giving error to as following
Command :-
gcc -shared -fPIC -o libJNI JNI.o libmymath.so
libJNI :- Library that should go in JNI.java, System.loadLibrary()
JNI.o :- Compiled JNI.c
libmymath.so :- my library that contains basic add, sub, mul, and division function
/usr/bin/ld: JNIPart.o: relocation R_X86_64_PC32 against undefined symbol `add' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: ld returned 1 exit status
If helper want more information, i'll be more specific and any help will be appreciated
Help me.
Thanks,
Axit Soni
Q: My libJNI Library Should Contain Both my own libmymath.so and JNI.o. Am i Right?
It sounds like your JNI.o calls code in libmymath.so. So yes, you need to specify libmylibmath.so in your link command, and you also need to make sure it's available at runtime.
Q: When I am Trying to Generate the .so which is Combination of libmymath.so and JNI.o. It is giving error undefined symbol 'add' can not be used when making a shared object; recompile with -fPIC
I would run "nm" against libmymath.so and make sure you actually have an "add". Perhaps you inadvertantly compiled one or more functions with C++, and the name is mangled?
It wouldn't hurt to do what the error says, and make sure everything is consistently built with "-fPIC".
Hi guys i have tried all the solutions like
java -Djava.library.path=. demo
adding the dll path to PATH
java -Djava.library.path=c:\JNI\demo.dll demo
But still the above error.
Here is my java code..
class demo
{
public native void printline();
public static void main(String[]args)
{
new demo().printline();
}
}
Here is my c code...
#include<stdio.h>
#include<jni.h>
#include "demo.h"
JNIEXPORT void JNICALL Java_demo_printline(JNIEnv *a, jobject b)
{
printf("Hello wrold!!!");
return;
}
Steps for compiling and running,
javac demo.java
javah demo
gcc -c -I"c:\jdk1.7.0_55\include" -I"c:\jdk1.7.0_55\include\win32" demo.c
gcc -Wl,--add-stdcall-alias -shared -o demo.dll demo.c
java -Djava.library.path=c:\JNI\demo.dll demo
Am i going wrong somewhere?
can someone please help me out,.
Try Run-Time Loading of the dll file within the java code in a static block like:
static
{
System.loadLibrary("demo");
}
should give you the output.
Moreover make sure that dll file generated is x32 or x64 according to the gcc compiler in use.
looking for "JNI hello world" (or many other terms, possibly), would have given you the answer.
for example:
http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
you need to load the library inside your java code
you need to specify the path to the directory of the library, not to the library itsself, in java.library.path
I've try the Hello world JNI from:
http://home.pacifier.com/~mmead/jni/cs510ajp/
I did the Java class:
public class ACTICamWrapperJNI {
public native void displayMessage();
static
{
System.loadLibrary("HelloWorldImp");
}
}
and call it in:
public static void main(String args[]) {
//</editor-fold>
System.out.println(System.getProperty("java.library.path"));
ACTICamWrapperJNI test = new ACTICamWrapperJNI();
}
the cpp file looks like:
#include <stdio.h>
#include "HelloWorld.h" // this header file was generated by javah
JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
}
I have switch to JDK x86 and compiled with X86:
C:\Development\testJNI>javac HelloWorld.java
C:\Development\testJNI>javac HelloWorld.java
C:\Development\testJNI>javah -jni HelloWorld
I used the gcc of MINGW32 I had in QT folder (hope that is ok)
C:\Development\testJNI>gcc -shared -I "C:\Program Files (x86)\Java\jdk1.7.0_40\include" -I"C:\Program Files (x86)\Java\jdk1.7.0_40\include\win32" HelloWorld.cpp -o HelloWorldImp.dll
Note I had to add shared otherwise I got the error:
undefined reference to `WinMain#16'
C:\Development\testJNI>"C:\Program Files (x86)\Java\jdk1.7.0_40\bin\java.exe" Main
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld.displayMessage()V
at HelloWorld.displayMessage(Native Method)
at Main.main(Main.java:9)
Note that I've make sure that I'm running the java of x32 jdk and compiled with the x32 version too as I have the x64 on my system too.
Tried on NetBean IDE as well and got the issue:
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Windows\System32\HelloWorldImp.dll: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary1(ClassLoader.java:1957)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1882)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1872)
at java.lang.Runtime.loadLibrary0(Runtime.java:849)
at java.lang.System.loadLibrary(System.java:1087)
at au.com.ricor.ACTICamWrapperJNI.<clinit>(ACTICamWrapperJNI.java:15)
at au.com.ricor.CameraPanel.main(CameraPanel.java:58)
As well the version of gcc I use is:
C:\Development\testJNI>gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/qt/tools/mingw48_32/bin/../libexec/gcc/i686-w64-mingw32/4
.8.0/lto-wrapper.exe
Target: i686-w64-mingw32
Configured with: ../../../src/gcc-4.8.0/configure --host=i686-w64-mingw32 --buil
d=i686-w64-mingw32 --target=i686-w64-mingw32 --prefix=/mingw32 --with-sysroot=/t
emp/x32-480-posix-dwarf-r2/mingw32 --enable-shared --enable-static --disable-mul
tilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-
threads=posix --enable-libgomp --enable-lto --enable-graphite --enable-checking=
release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --d
isable-sjlj-exceptions --with-dwarf2 --disable-isl-version-check --disable-cloog
-version-check --disable-libstdcxx-pch --disable-libstdcxx-debug --disable-boots
trap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --d
isable-symvers --with-gnu-as --with-gnu-ld --with-arch=i686 --with-tune=generic
--with-host-libstdcxx='-static -lstdc++' --with-libiconv --with-system-zlib --wi
th-gmp=/temp/mingw-prereq/i686-w64-mingw32-static --with-mpfr=/temp/mingw-prereq
/i686-w64-mingw32-static --with-mpc=/temp/mingw-prereq/i686-w64-mingw32-static -
-with-isl=/temp/mingw-prereq/i686-w64-mingw32-static --with-cloog=/temp/mingw-pr
ereq/i686-w64-mingw32-static --enable-cloog-backend=isl --with-pkgversion='rev2,
Built by MinGW-builds project' --with-bugurl=http://sourceforge.net/projects/mi
ngwbuilds/ CFLAGS='-O2 -pipe -I/temp/x32-480-posix-dwarf-r2/libs/include -I/temp
/mingw-prereq/x32-zlib/include -I/temp/mingw-prereq/i686-w64-mingw32-static/incl
ude' CXXFLAGS='-O2 -pipe -I/temp/x32-480-posix-dwarf-r2/libs/include -I/temp/min
gw-prereq/x32-zlib/include -I/temp/mingw-prereq/i686-w64-mingw32-static/include'
CPPFLAGS= LDFLAGS='-pipe -L/temp/x32-480-posix-dwarf-r2/libs/lib -L/temp/mingw-
prereq/x32-zlib/lib -L/temp/mingw-prereq/i686-w64-mingw32-static/lib -L/temp/x32
-480-posix-dwarf-r2/mingw32/opt/lib'
Thread model: posix
gcc version 4.8.0 (rev2, Built by MinGW-builds project)
Thanks
William
Either rename the class from au.com.ricor.ACTICamWrapperJNI to HelloWorld, or the native function (in C++ file) from Java_HelloWorld_displayMessage() to Java_au_com_ricor_ACTICamWrapperJNI_displayMessage()
I know this has an answer, but I determined that if you are compiling as Debug, it is not redistributable to another PC; you can try compiling for Release, and that should work. I just used this to resolve my own issue.
I'm trying to call a C function inside a Java code.
I have this hava code.
public class JavaToC {
public native void helloC();
static {
System.loadLibrary("HelloWorld");
}
public static void main(String[] args) {
new JavaToC().helloC();
}
}
. I compiled it and then created header file. Then make the following HelloWorld.c file.
#include <stdio.h>
#include <jni.h>
#include "JavaToC.h"
JNIEXPORT void JNICALL Java_JavaToC_helloC(JNIEnv *env, jobject javaobj)
{
printf("Hello World: From C");
return;
}
I tried compiling this using "gcc -o libHelloWorld.so -shared -I/usr/java/include -I/usr/java/include/solaris HelloWorld.c -lc", but it gives the following result.
Text relocation remains referenced
against symbol offset in file
.rodata (section) 0x9 /var/tmp//cc.GaGrd.o
printf 0xe /var/tmp//cc.GaGrd.o
ld: fatal: relocations remain against allocatable but non-writable sections
collect2: ld returned 1 exit status
I'm working on Solaris 11, how can I solve this?
I cannot test this on a Solaris machine at the moment, but from http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/SPARC-Options.html
-mimpure-text suppresses the “relocations remain against allocatable but non-writable sections” linker error message. However, the
necessary relocations will trigger copy-on-write, and the shared
object is not actually shared across processes. Instead of using
-mimpure-text, you should compile all source code with -fpic or -fPIC.
the solution seems to be to add the -fpic option to generate position-independent code.
I want to call a C subroutine from Java. I'm using JNI. I have created the .java, .c, and .h files, and compiled a DLL. All the files are in the same folder. But when I run the program, it shows an unsatisfiedlinkError. Where am I going wrong...?
As I am learning JNI, the source code I used is the one from: http://www.ibm.com/developerworks/java/tutorials/j-jni/section2.html and things I have already tried:
Create a dll using Code::Blocks(ide) and GCC as the compiler
Create dll using GCC from command line (Ref. http://sig9.com/node/35 )
I am using Win7 32 bit, and I guess all the methods above generate 32-bit DLLs
All the solutions I found for creating a DLL (shared library) are for MS VC/VCPP and I don't have that on my machine right now.
Where is the problem? DLL files are being generated without any exception, but when I run the Java code, it throws the exception.
PS: If there is any theoretical examples that explains how JNI works and what actually it does, then kindly share the link...
The message or exception being thrown:
c:\myjava1>java Sample1
Exception in thread "main" java.lang.UnsatisfiedLinkError: Sample1.intMethod(I)I
at Sample1.intMethod(Native Method)
at Sample1.main(Sample1.java:11)
At the end of the day after creating dll file lots of times,I am pretty sure that there is possibly no issue with it ,something is wrong with the path ...I have changed the loadlibrary method with load method ,but still no luck,.....
as suggested by a MOD:
I have been discussing about this question on the post:JNI error while calling a C subroutine ,I am posting all the codes here as the comments have limited characters... Sample1.c
#include "jni.h"
#include"Sample_Sample1.h"
JNIEXPORT jint JNICALL Java_Sample_Sample1_test(JNIEnv *env, jobject obj){
return(1);
}
void main(){}
Sample1.java
package Sample;
public class Sample1
{
public native int test();
static{
System.loadLibrary("Sample1");
}
public static void main(String[] args)
{
Sample1 sample = new Sample1();
System.out.println(sample.test());
}
}
Sample_Sample1.h(generated using javah -jni command)
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class Sample_Sample1 */
#ifndef _Included_Sample_Sample1
#define _Included_Sample_Sample1
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Sample_Sample1
* Method: test
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_Sample_Sample1_test
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Can anyone guide me where the issue is?In earlier post I mentioned that the code I am using is the one from tutorials ,but to simplyfy the things I have changed the codes ...While using **java Sample.Sample1" i am getting:
c:\myjava1>java Sample.Sample1
Exception in thread "main" java.lang.UnsatisfiedLinkError: Sample.Sample1.test()I
at Sample.Sample1.test(Native Method)
at Sample.Sample1.main(Sample1.java:12)
You need to have your library explicitly set on your path.
It may be the case that the flags you are using there aren't quite right. Try this:
gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at \
-I[Java_HOME]/include -I[Java_HOME]/include/win32 \
-shared -o Sample1.dll Sample1.c
From MinGW GCC site.
Have you checked your DLL by calling it from a stub C++ application? Pay particular attention to the exact name (including capitalisation) of the method(s) you are calling.
The Javadoc for UnsatisfiedLinkError says "Thrown if the Java Virtual Machine cannot find an appropriate native-language definition of a method declared native." That probably means either that the name is misspelled or your DLL is not where the JVM is expecting to find it.
Finally solved the problem using System.load() method, System.loadLibrary() Still doesn't work for me...it keeps on giving the same exception, And the I think the issue was with the .dll Thanks to all of you who supported and responded...
After spending 2hrs and analysing the code. Problem is with .dll/.so compilation. Below command works for me:
g++ -dynamiclib HelloJni.cpp -I /usr/include/ -I /usr/lib/jvm/java-1.8.0-openjdk-amd64/include/ -I /usr/lib/jvm/java-1.8.0-openjdk-amd64/include/linux/ -shared -o libHelloJni.so
or
g++ -dynamiclib HelloJni.cpp -I /usr/include/ -I $JAVA_HOME/include/ -I $JAVA_HOME/include/linux/ -shared -o libHelloJni.so
Above command is for linux. In case of Windows, change
[Java_HOME]/include/linux/ ---> [Java_HOME]/include/win/
Mac:
$Java_HOME/include/linux/ ---> $Java_HOME/include/darwin/