JNI UnsatisfiedLinkError

F

Frank

Hi,

I am trying to add some java interface to existing c++ libraries. The
libraries were compiled on linux with gcc 3.2.2. I am using SDK 1.4.2.
The same libraries were compiled with c++ test main function and it
works fine. I do have to include additional libraries such as stdc++
and uuid for the test app to build properly.

When I run the java test app, it complains that within one of the
library, an undefined symbol: _ZNSsC1EPKcRKSaIcE was encountered. I
found this symbol in libstdc++.so flagged as a weak dynamic symbol
using

nm -D /usr/lib/libstdc++.so

But loading stdc++ didn't change anything. I wonder if anyone has
experienced this and how it was resolved.

Thanks in advance,

Frank
 
G

Gordon Beaton

When I run the java test app, it complains that within one of the
library, an undefined symbol: _ZNSsC1EPKcRKSaIcE was encountered. I
found this symbol in libstdc++.so [...]
But loading stdc++ didn't change anything. I wonder if anyone has
experienced this and how it was resolved.

Specify -lstdc++ when you link your shared object.

/gordon
 
F

Frank

Gordon Beaton said:
Specify -lstdc++ when you link your shared object.

Thanks. This did get around the loading problem. Now I ran into the
UnsatisfiedLinkError during runtime. I saw from other posts that the
function names are mangled when linker creates the library. How can I
let the JVM find the proper function?

Frank
 
G

Gordon Beaton

Thanks. This did get around the loading problem. Now I ran into the
UnsatisfiedLinkError during runtime. I saw from other posts that the
function names are mangled when linker creates the library. How can I
let the JVM find the proper function?

The linker doesn't mangle the symbol names, but the C++ compiler
might.

Your native methods should be declared "extern C" so they won't be
mangled. If you included the file generated by javah and used the
*exact* same method signatures, then the "extern C" declaration in the
header file is sufficient.

If your class belongs to a package, you should have used the fully
qualified classname (i.e. including the package name) when you ran
javah, or the generated names won't be correct.

You can use nm to check what the .so file actually contains.

The exact text of the exception might provide more clues.

/gordon
 
F

Frank

Gordon Beaton said:
The linker doesn't mangle the symbol names, but the C++ compiler
might.

The exact text of the exception might provide more clues.

/gordon

The function name is definitely mangled. I checked with nm. The source
file is in c++. It does not belong to any package. The exception says
the following:

Exception in thread "main" java.lang.UnsatisfiedLinkError:
identifyEssenceType
at Essence.identifyEssenceType(Native Method)
at Essence.main(Essence.java:29)


****************
Another exception has been detected while we were handling last error.
Dumping information about last error:
ERROR REPORT FILE = (N/A)
PC = 0x00000021
SIGNAL = 11 (VM shutdown)
FUNCTION NAME = (N/A)
OFFSET = 0xFFFFFFFF
LIBRARY NAME = (N/A)
Please check ERROR REPORT FILE for further information, if there is
any.
Good bye.

The C++ source file is:

static Wrapper wrapper;

JNIEXPORT jstring JNICALL Java_Essence_identifyEssenceType
(JNIEnv *env, jclass cls, jstring filename)
{
std::string buf;
const char *str;

str = env->GetStringUTFChars(filename, NULL);
if (str == NULL)
{
return NULL; /*OutOfMemoryError already thrown */
}

printf("%s", str);
wrapper.IdentifyEssenceType(str, buf);

env->ReleaseStringUTFChars(filename, str);

return env->NewStringUTF(buf.c_str());
}

Java source is:

public class Essence {
private String name;
private int type;
public native String identifyEssenceType(String filename);

public Essence()
{
name = "";
type = 0;
}

public static void main(String[] args) {
Essence essence = new Essence();
String fileType;

fileType = essence.identifyEssenceType("test.mpg");
System.out.println("file type is" + fileType);
}

static {
System.loadLibrary("mxf");
System.loadLibrary("klv");
System.loadLibrary("jmxf");
}
}

Thanks for your help.

Frank
 
G

Gordon Beaton

The function name is definitely mangled. I checked with nm.
[...]

JNIEXPORT jstring JNICALL Java_Essence_identifyEssenceType
(JNIEnv *env, jclass cls, jstring filename)

You changed the signature. The type of the second argument is jobject,
not jclass. Apparently the method used to be declared "static" in the
Java source.

That means that the symbol declared in Essence.h isn't the same as
this one, so the "extern C" doesn't have the desired effect and the
name got mangled.

/gordon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top