JNI - unresolved _ZNSs4_Rep11_S_terminalE

F

FBergemann

Hi all,

I try to load a C++ shared library for executing a main-driver for
send/receive of messages, which (the main-driver) calls JAVA again to
do the real work for processing the message (both via JNI).

I assume, that there could be a couple of more pitfalls to this
approach - but i get already problems to start the proper module:
I get following error message, when starting the JAVA MainWrapper
class:

exception in thread "main" java.lang.UnsatisfiedLinkError:
<...>/run/lib/libBSproxy.so.1.0: ld.so.1: /usr/j2se/bin/sparcv9/java:
fatal: relocation error: file <...>/run/lib/libBSproxy.so.1.0: symbol
_ZNSs4_Rep11_S_terminalE: referenced symbol not found
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1473)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1397)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:832)
at MainWrapper.<clinit>(BSproxy.java:18)

JAVA:
=====

// do the real work per message here:
class Process {

public static void doit(String msg) {
System.out.println("[Process::doit: " + msg + "]");
}
}

// invoke the C++ main loop here:
class MainWrapper {
public native int loop();

public String message_data;

static {
System.out.println("load shared libraries...");
System.out.println("->BSproxy");
System.loadLibrary("BSproxy");
System.out.println("...done");
}

// embed a main() here as static to start once for this class
public static void main(String[] args) {

MainWrapper main_wrapper = new MainWrapper();
int status = main_wrapper.loop();
}

}

C++:
====
#include <iostream>
#include <jni.h>

// JNI stuff
#include "BSproxy_loop.h"

static JNIEnv *my_jni_env_glb = 0L;

class MyServer: private ComLayer::Server
{

public:
MyServer(const std::string& cfg, const std::string& name):
shutdown(this) {
new ComLayer::Listener(this, new
ComTransport::TcpService(cfg, name, 1));
cnt=0;
}

void AttachConnection(ComLayer::Connection *con)
{ ...
}

void DetachConnection(ComLayer::Connection *con)
{ ...
}

// callback function for
// 1. receiving a message,
// 2. process it and
// 3. return the response
void MsgReady(ComLayer::Connection *con)
{ std::string input;
std::string output;

con->GetMsg(input);

// now call JAVA again to process the msg
// --------------------------------------
jclass processing_cls =
my_jni_env_glb->FindClass("Processing");
jmethodID doit_f =
my_jni_env_glb->GetStaticMethodID(processing_cls, "doit",
"(Ljava/lang/String;)V");

// jump to JAVA processing
// stat = ProcessJava(input, output)
output = input;

con->PutMsg(output);
}

};

JNIEXPORT jint JNICALL
Java_MainWrapper_loop(JNIEnv *env, jobject obj) {
char *name="BSproxy";
char *cfg="BSproxy.cfg";
int c;

my_jni_env_glb = env;

std::cout << "test\n";

MyServer server(cfg, name);

// this method won't return to JAVA
// but MsgReady is called and invokes JAVA again

// internal function of the C++ lib
ProcessEvents();

return (jint)0;
}


The purpose of the whole story is to re-use the C++ main driver (for
message communication protocol) as is.

I know, the _ZNSs4_Rep11_S_terminalE comes from g++ include file
<...>/gcc-3.3.5/include/bits/basic_string.h
But i don't get it compiled into the shared library libBSproxy.so
And i can't find a shared library, which holds it (but to be honest we
don't have installed liststdc++.so - only the static one).

Do i necessarily need the dynamic lib liststdc++.so?
Or is there any other work-around?

- Many Thanks!

Regards!

Frank
 
G

Gitta Zahn

Hello Frank,

I get following error message, when starting the JAVA MainWrapper
class:

exception in thread "main" java.lang.UnsatisfiedLinkError:
<...>/run/lib/libBSproxy.so.1.0: ld.so.1: /usr/j2se/bin/sparcv9/java:
fatal: relocation error: file <...>/run/lib/libBSproxy.so.1.0: symbol
_ZNSs4_Rep11_S_terminalE: referenced symbol not found
I know, the _ZNSs4_Rep11_S_terminalE comes from g++ include file
<...>/gcc-3.3.5/include/bits/basic_string.h

I never tried this with the GNU libraries but I would suggest using
the dynamic libraries. They should be installed/symbolic link
available under /usr/local/lib or /usr/lib.
Don't forget to set the LD_LIBRARY_PATH correctly - it must contain
at least these directories.

Just a little remark to your source code:
The JNIEnv* is only valid in the current thread - so storing this in a
static variable will not work in a multi threaded process. Call
GetEnv() to obtain the current environment before upcalling to Java
instead. If you want to start additional threads from the native side
you have to manually attach them to the JVM.

In JNI operations you should catch all C++ exceptions and handle them
appropriately, e.g. by re-throwing them as Java exceptions via
ThrowNew().

Gitta
 
F

FBergemann

Hello Gitta,

Gitta said:
Hello Frank,

I never tried this with the GNU libraries but I would suggest using
the dynamic libraries. They should be installed/symbolic link
available under /usr/local/lib or /usr/lib.
Don't forget to set the LD_LIBRARY_PATH correctly - it must contain
at least these directories.

Did this, but with another dedicated lib directory (not /usr/lib/ or
/usr/local/lib - but set the LD_LIBRARY_PATH properly).
It still doesn't work - the result is still:

padsol02 1082> /usr/j2se/bin/sparcv9/java -d64 MainWrapper
load shared libraries...
->BSproxy
Exception in thread "main" java.lang.UnsatisfiedLinkError:
/nfs-serv-2/buildspace/FBergemann/OPSC_Gold_rte_dev_R0.2.1/run/lib/libBSproxy.so.1.0:
ld.so.1: /usr/j2se/bin/sparcv9/java: fatal: relocation error: file
/nfs-serv-2/buildspace/FBergemann/OPSC_Gold_rte_dev_R0.2.1/run/lib/libBSproxy.so.1.0:
symbol _ZNSs4_Rep11_S_terminalE: referenced symbol not found
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1473)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1397)
at java.lang.Runtime.loadLibrary0(Runtime.java:788)
at java.lang.System.loadLibrary(System.java:832)
at MainWrapper.<clinit>(MainWrapper.java:15)

I will extend another JNI example of mine and use std:string there to
see, if it also fails.
Just a little remark to your source code:
The JNIEnv* is only valid in the current thread - so storing this in a
static variable will not work in a multi threaded process. Call
GetEnv() to obtain the current environment before upcalling to Java
instead. If you want to start additional threads from the native side
you have to manually attach them to the JVM.

In JNI operations you should catch all C++ exceptions and handle them
appropriately, e.g. by re-throwing them as Java exceptions via
ThrowNew().

Got this - thanks for the hint!

Best regards!

Frank
 

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,755
Messages
2,569,537
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top