JNI & Thread question

G

Guest

Hopefully this is an easy question.

Suppose I've got a native method that declares a bunch of memory based
on input parameters, does some work, and then returns a jintArray with
the results. ie, something like this:

JNIEXPORT jintArray JNICALL
Java_Me_doSomething (JNIEnv *jniEnv, jobject jobj, jint jx, jint jy)
{
int x = (int) jx;
int y = (int) jy;

jint mem[x * y];
for (int j = 0; j < y; j++)
for (int i = 0; i < x; i++)
mem[j * x + i] = getSomeValueSomehow ();

jintArray data = jniEnv->NewIntArray (x * y);
jniEnv->SetIntArrayRegion (data, 0, x * y, mem);
free (mem);
return data;
}

And, suppose that my Java program creates several Threads, all of
which call the native doSomething () method with their own params.

My question is this: is there any chance that the C++ function's
mem array can get corrupted based on the different Threads calling
doSomething? If so, then will wrapping the call to doSomething ()
inside a synchronized method prevent corruption? I'm getting
random SIGBUS and SIGSEG faults that are proving very difficult to
track down on the Solaris platform I'm using.

TIA,
 
D

Denis

Your code is absolutely thread safe, no need for synchronized blocks
etc (except, maybe, if contents of getSomeValueSomehow() requires it).

Are you sure you need to do "free(mem)"? I suppose the line "jint
mem[x*y]" allocates memory on the stack using alloca(), so it is freed
automatically. If I am right, then call to free() is erroneous, and you
have to remove it.

Denis
 
R

Roedy Green

My question is this: is there any chance that the C++ function's
mem array can get corrupted based on the different Threads calling
doSomething?

The practical question what are my odds something WON'T get corrupted
if I start using multiple threads in my JNI code.

First let's discard the tricky spawning native threads.

Let's focus on the basics of how to make JNI threadsafe for Java
threads.

the JNIEnv pointer is valid only for the thread associated with it.
Don't pass it around.

Local references are only valid in the thread that created them.

you can convert a local reference to global reference to share it.

You have the same sorts of synchronised problems in JNI you do in
regular java, it is just you deal with them with MonitorEnter and
MonitorExit

Threads in JNI are quite a can of worms since you can mix native a
Java thread mechanisms.

I think you are wise to deal with the synchronisation out of JNI to
help simplify.
 
C

Chris Uppal

Denis said:
Are you sure you need to do "free(mem)"? I suppose the line "jint
mem[x*y]" allocates memory on the stack using alloca(), so it is freed
automatically. If I am right, then call to free() is erroneous, and you
have to remove it.

Agreed. I just wanted to add that if x*y is large, then you'll be allocating a
large array on the stack. People have reported problems with using large
amounts of stack space on threads "owned" by Java. If that is the case then
it'd be better to use malloc()/free() (or similar) to create the array space.

An alternative would be to use the space allocated by Java for the returned
value directly. Create the array, and use GetIntArrayElements() /
ReleaseIntArrayElements(COMMIT) to get a pointer to the start of an int[] into
which you can write directly.

-- chris
 
G

Gordon Beaton

I'm getting random SIGBUS and SIGSEG faults that are proving very
difficult to track down on the Solaris platform I'm using.

Is this your only native method?

Perhaps x*y*sizeof(int) is too large for the stack, as Chris mentioned
in another post. Here's a technique that doesn't require the
additional array:

jintArray data = jniEnv->NewIntArray(x * y);
int *mem = jniEnv->GetIntArrayElements(data,NULL);

for (j...) {
for (i...) {
mem[j*x + i] = getValue();
}
}

jniEnv->ReleaseIntArrayElements(data,mem,0);

return data;

/gordon
 
H

Hack Bert

jint mem[x * y];

How do you get this line to compile ? I assume since you are doing a
free(mem) later, that you are using something like

jint *mem = (jint *) malloc(x*y*sizeof(jint));

here.

nowadays malloc and free are thread safe (see your c compilers runtime
documentation (try out a 'man malloc')) and you should have no problem
allocating memory as you need it - assuming you have enough free virtual
address space in your application.

and btw: the memory allocated by malloc is not on a threads stack but
'somewhere' in your address space.

Hack Bert
 

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,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top