JNI and global variables in shared libs

D

Drazen Gemic

This might not be the correct newsgroup for this question, but I am just
not sure. I need some starting point.

I am trying to call some third party C code via JNI. It appears to be
working. The operating system is Linux. Third party code was meant to
be a command line program, but I managed to create shared library.

The code is huge, spread across multiple ".c" and ".h" files, and I
wonder is it thread safe, because Java code will be multithreaded. The
questions are:

- if it contains global variables do all threads share the same instance
of the global C variable, or they are "per thread" ?

- if it contains global static C variables do all threads share the same
instance of the global C variable, or they are "per thread" ?

- what about static C variables in C functions ?

thanks in advance

DG
 
R

Roedy Green

The code is huge, spread across multiple ".c" and ".h" files, and I
wonder is it thread safe, because Java code will be multithreaded. The
questions are:

- if it contains global variables do all threads share the same instance
of the global C variable, or they are "per thread" ?

- if it contains global static C variables do all threads share the same
instance of the global C variable, or they are "per thread" ?

- what about static C variables in C functions ?

The way to handle this is with synchronized Java methods wrapping the
native methods that let only one thread at a time into the C side.

If your C code has some totally independent parts, you can control
access separately so that you could have two threads on the C side at
a time, but not both in the same C code section.

Once that is all working, and only if things are too slow, you might
look into how to make some parts of the C code thread safe, or how to
partition the C code into smaller independent sections.

In the long term, you might gradually bring over crucial functionality
from the C side to the Java side for ease of maintenance and easier
thread integration.
 
T

Thomas Fritsch

Roedy Green said:
The way to handle this is with synchronized Java methods wrapping the
native methods that let only one thread at a time into the C side.
Why not simply declare the native methods synchronized, for example:
native synchronized void someMethod();
thus omitting the mentioned wrapping Java methods?
 
R

Roedy Green

Why not simply declare the native methods synchronized, for example:
native synchronized void someMethod();
thus omitting the mentioned wrapping Java methods?

The reason I would done that it is to ensure it was not my problem to
deal with the synchronisation on the C side where it would be messier.
It would be just one less uncertainty. I like to do as much as
possible on the Java side.

I often make native functions private so that I could reimplement
them more easily partitioning the work differently for the Java/C
side on different platforms. I have a wrapper anyway.

An example would be this code to get the Windows last accessed file
time in Java format.

/**
* get last access date of a file. This may be 2 hours out of date
since
* windows does not attempt to keep immediately up to date.
*
* @param filename
* Name of file to request date on.
* @return Java timestamp when file was last accessed, 0 = problem
*/
public static long getFileLastAccessed ( String filename )
{
long whenFileLastAccessed = nativeGetFileLastAccessed(
filename );
return whenFileLastAccessed == 0 ? 0 : ( whenFileLastAccessed
/ 10000 )
- diffInMillis;
}

where nativeGetFileLastAccessed is private.
 
C

Chris Uppal

Drazen said:
- if it contains global variables do all threads share the same instance
of the global C variable, or they are "per thread" ?

- if it contains global static C variables do all threads share the same
instance of the global C variable, or they are "per thread" ?

- what about static C variables in C functions ?

You have correctly identified the features of C/C++ code that are inherently
not thread-safe.

If you use any of those features in threaded code then you have to take
additional steps to ensure that no two threads can ever access them at the same
time. You could do that in your "glue" code (the JNI DLL) using OS-specific
features to ensure thread safety (semaphores, mutexes, and so on), or you can
use Java's synchronisation to the same effect. Using Java's features is
simplest, but it may not easily provide as much fine-grained control to allow
you to maximise the concurrent use of your C code (e.g if there are two
functions that /don't/ share data hen you can safely call them both at the same
time in different threads). Others have already talked about how to do that in
Java; I only want to add that you should ensure that all the "synchronized"
methods are actually invoked on the /same/ object or else the Java runtime
won't realise that there is any reason to stop two threads running your code at
the same time. Another way to get the same effect is to make all (no
exceptions!) the native methods "static" (and synchronised) so that they all
synchronise on the class object.

BTW, you should also ensure that your C DLL is liked with a version of the
C/C++ runtime library (for malloc() etc) that has been written to be
thread-safe. You may already have done that, or -- for all I know -- the Linux
libraries may all be inherently threadsafe, but it's worth mentioning, just in
case...

-- chris
 
D

Drazen Gemic

Thank you all. I have some more information, now.

Yes, the code is by all means thread unsafe, I have tried to run it from
a couple threads.

I can not run the code as a synchronized section of the application,
because the application is multithreaded server, and it is going to
be to slow if the clients are processed one at the time. There might
be some timeouts due to irregular conditions on the network, and all
other clients would have to wait when it happens.

I will have to run the code as a separate processes executed from the
threads. I had some problems even with that (UDP ports, packet ID's),
but I have modified C the code.

The code is radius PAP to EAP-TTLS bridge, a piece of middleware between
old Cisco access server and Radius proxy server.

DG
 

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,955
Messages
2,570,117
Members
46,705
Latest member
v_darius

Latest Threads

Top