Java Forum / Virtual Machine / February 2004
jni - problems when loading shared library
Damjan - 19 Feb 2004 10:28 GMT Hi guys I need some help. I've made a little program written in c that compiles well with gcc. After compiling, i created a shared library with ld, without any problems again. But, when trying to load the library from a java code, i get an error saying:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/damjan/jbproject/progetto/classes/progetto/libfasta.so: /home/damjan/jbproject/progetto/classes/progetto/libfasta.so: undefined symbol: _ZNSaIcEC1Ev at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1560) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1485) at java.lang.Runtime.loadLibrary0(Runtime.java:788) at java.lang.System.loadLibrary(System.java:834) at progetto.Mojpanel.<clinit>(Mojpanel.java:20)
Here is my code:
#include <jni.h> #include "Frame1.h" #include <cstring> #include <fstream> #include <iostream>
#include "c++/Biosequence.h"
extern "C" { using namespace std; JNIEXPORT void JNICALL Java_Frame1_fasta (JNIEnv *env, jobject obj, jstring fastaname) { Biosequence* s; const char *name = env->GetStringUTFChars(fastaname, 0); string fastapath = ""; fastapath = name; ifstream fin(fastapath.c_str()); if (!fin.is_open()) { cout << "Unable to open " << fastapath << endl; exit(1); } s = new Biosequence(fin); fin.close(); cout << s->getInfo() << endl; s->setName(fastapath); s->buildSuffixTree(SuffixTree::LAZY_STRATEGY); env->ReleaseStringUTFChars(fastaname, name); printf("Funzionaaaaaa!!\n"); } } // end extern "C"
One more thing: I tried to see some details of the library created with the linux comand nm, and realize that that probably the part of the code which is problematic is: std::allocator<char>::allocator() but i don't know why. Maybe for some string - char incompatibility.
P.S. I'm working on JBuilderX under Mandrake Linux 9.2 with jdk 1.4 P.P.S. I tried to make an equivalent selfstanding program in c without jni features, and it worked fine. Probably
Gordon Beaton - 19 Feb 2004 10:55 GMT > After compiling, i created a shared library with ld, without any > problems again. But, when trying to load the library from a java [quoted text clipped - 4 lines] > /home/damjan/jbproject/progetto/classes/progetto/libfasta.so: undefined > symbol: _ZNSaIcEC1Ev Specify -lstdc++ when you link your shared library.
If you'd linked using gcc (g++) instead of ld (as is usually recommended these days), I believe this would have been done for you.
/gordon
 Signature [ do not email me copies of your followups ] g o r d o n + n e w s @ b a l d e r 1 3 . s e
Damjan - 19 Feb 2004 12:57 GMT >> After compiling, i created a shared library with ld, without any >> problems again. But, when trying to load the library from a java [quoted text clipped - 11 lines] > > /gordon I still didn't get it... sorry but I'm a newbie in this. How can I make a shared library libxxx.so with gcc? Now I'm using gcc only to compiling, like this: gcc -I/home/damjan/JBuilderX/jdk1.4/include -I/home/damjan/JBuilderX/jdk1.4/include/linux -c Unifier.cpp and after that ld -shared -o libfasta.so Unifier.o to create a library 'libfasta'. and when I tried to link with '-l stdc++' or '-lstdc' I got this: [damjan@localhost progetto]$ ld -l stdc++ -shared -o libfasta.so Unifier.o ld: cannot find -lstdc++
Damjan
Gordon Beaton - 19 Feb 2004 15:25 GMT > I still didn't get it... sorry but I'm a newbie in this. > How can I make a shared library libxxx.so with gcc? gcc -fPIC -D_REENTRANT -I [...] -c Unifier.cpp gcc Unifier.o -o libfasta.so -lstdc++
/gordon
 Signature [ do not email me copies of your followups ] g o r d o n + n e w s @ b a l d e r 1 3 . s e
Gordon Beaton - 19 Feb 2004 15:57 GMT On 19 Feb 2004 16:25:41 +0100, I wrote:
> gcc -fPIC -D_REENTRANT -I [...] -c Unifier.cpp > gcc Unifier.o -o libfasta.so -lstdc++ Sorry:
gcc -shared Unifier.o -o libfasta.so -lstdc++
/gordon
 Signature [ do not email me copies of your followups ] g o r d o n + n e w s @ b a l d e r 1 3 . s e
Matthias - 25 Feb 2004 20:14 GMT Hi Guys!
I have nearly the same problem! I want to write a Java-Wrapper for a C++-Library! Ok, i have read some JNI-Tuts, and some simple testing-programs worked fine!
Ok, i will post some code-referneces, because i think, its the best way to explain my problem!
Note: the C++-Library is known as 'Irrlicht'!
The header file for the whole (jni).c files is: #include <jni.h> #include <irrlicht.h>
#pragma comment(lib, "Irrlicht.lib")
I compile the (jni).c files with the following Makefile: OPTS = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux -I"$HOME/irrlicht/include" -I"/usr/X11R6/include" -L"/usr/X11R6/lib" -L"$HOME/irrlicht/lib/Linux" -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lz -ljpeg
all: $(CXX) -fPIC -lstdc++ -shared $(OPTS) "(jni).cpp-files" -o my_library.so
(-lGL -lXxf86vm -lXext -lX11 -lz -ljpeg is needed by the Irrlicht-library!!!!)
Ok, i get the following error, when i want to start the java-program: Exception in thread "main" java.lang.UnsatisfiedLinkError: $HOME/my_library.so: $HOME/my_library.so: undefined symbol: _ZN3irr12createDeviceENS_5video11EDriverTypeERKNS_4core11dimension2dIiEEjbbPNS_14IEventReceiverEPKw at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1560) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1456) at java.lang.Runtime.load0(Runtime.java:737) at java.lang.System.load(System.java:811) at Main.<clinit>(Main.java:31)
When i type "nm -f my_library.so" in the console i get the following error: w __cxa_finalize@@GLIBC_2.1.3 w __gmon_start__ U __gxx_personality_v0@@CXXABI_1.2 w _Jv_RegisterClasses U _ZN3irr12createDeviceENS_5video11EDriverTypeERKNS_4core11dimension2dIiEEjbbPNS_14IEventReceiverEPKw
I don't know why the function is so "crypted" but it means, that the problem is happening, when calling the function createDevice(EDriverType, dimension2d<32>(w, h), etc.)
Ok, i hope you can help me, and if you need further information i will post them!!
thanks in advange! matthias
Gordon Beaton - 26 Feb 2004 07:29 GMT > Ok, i get the following error, when i want to start the java-program: > Exception in thread "main" java.lang.UnsatisfiedLinkError: [quoted text clipped - 6 lines] > at java.lang.System.load(System.java:811) > at Main.<clinit>(Main.java:31) [...]
> I don't know why the function is so "crypted" but it means, that the > problem is happening, when calling the function > createDevice(EDriverType, dimension2d<32>(w, h), etc.) Is createDevice() a native method declared in your Java class, and defined in the library?
To prevent the C++ compiler from mangling the symbol name, your native method *must* be declared with: extern "C"
This is done automatically for you if you include the header file generated by javah *and* your functions use the exact names and signatures found in that file. If you changed any of the names or argument types (don't!) the declaration in the generated header file isn't sufficient and you need to add the declaration yourself to the function definition.
If that doesn't help, post the contents of the generated header and relevant parts of the native code.
Note too that when you link, you should normally put the library flags (-lstdc++ etc) *after* the object files and other libraries that depend on them. See:
http://gcc.gnu.org/onlinedocs/gcc-3.3.2/gcc/Link-Options.html
/gordon
 Signature [ do not email me copies of your followups ] g o r d o n + n e w s @ b a l d e r 1 3 . s e
Matthias - 26 Feb 2004 18:57 GMT Hi!
Thanks for you quick answer! The header-file looks like this:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class jirr_Jirr */
#pragma comment(lib, "Irrlicht.lib")
#ifndef _Included_jirr_Jirr #define _Included_jirr_Jirr #ifdef __cplusplus extern "C" { #endif /* * Class: jirr_Jirr * Method: cpp_createDevice * Signature: (IIIIZZLjirr/JiEventReceiver;)Ljirr/JiDevice; */ JNIEXPORT jobject JNICALL Java_jirr_Jirr_cpp_1createDevice (JNIEnv *, jclass, jint, jint, jint, jint, jboolean, jboolean, jobject);
#ifdef __cplusplus } #endif #endif
and the corresponding cpp-file is: #include "jirr_Jirr.h" #include <irrlicht.h> using namespace irr;
using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui;
JNIEXPORT jobject JNICALL Java_jirr_Jirr_cpp_1createDevice (JNIEnv *env, jclass cls, jint type, jint width, jint height, jint bits, jboolean fullscreen, jboolean stencilbuffer, jobject receiver) {
IrrlichtDevice *device;
device = createDevice(type, dimension2d<s32>((s32)width, (s32)height), (u32)bits, (bool)fullscreen, (bool)stencilbuffer, 0); // here, java crashes!!!
return (jobject)device; //only for testing
}
I cant find any mistake!
Thanks in advange!!! matthias
Juergen Kreileder - 26 Feb 2004 20:12 GMT [...]
> I cant find any mistake! Read Gordon's last hint again
,----
| Note too that when you link, you should normally put the library flags | (-lstdc++ etc) *after* the object files and other libraries that | depend on them. See: | | http://gcc.gnu.org/onlinedocs/gcc-3.3.2/gcc/Link-Options.html `----
and change
,----
| OPTS = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/linux | -I"$HOME/irrlicht/include" -I"/usr/X11R6/include" -L"/usr/X11R6/lib" [quoted text clipped - 4 lines] | $(CXX) -fPIC -lstdc++ -shared $(OPTS) "(jni).cpp-files" -o | my_library.so `----
to something like
,----
| CXX_FLAGS = -D_REENTRANT -I $(JAVA_HOME)/include | -I $(JAVA_HOME)/include/linux -I"$HOME/irrlicht/include" [quoted text clipped - 6 lines] | $(CXX) -fPIC -shared $(CXX_FLAGS) "(jni).cpp-files" -o | my_library.so $(LD_FLAGS) `----
Juergen
 Signature Juergen Kreileder, Blackdown Java-Linux Team http://www.blackdown.org/java-linux/java2-status/
Matthias - 29 Feb 2004 12:40 GMT Thank you very much Gordon and especially Juergen! Now i can continue my work!
bye, Matthias!
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|