JNI string problem

A

Alex Hunsley

I have a JNI problem when calling native code from a java program. The
java program is passing in a non-empty String to the native code, but at
the native code level I crash out on a call to NewStringUTFChars using
the passed-in jstring. When I run with the -Xcheck:jni parameter, I get
the following output:

JVMCI161: FATAL ERROR in native method: JNI received a null string
at a.b.c.MyNativeMethod(Native Method)

(class + package names obscured)

So, it would appear that the jstring getting passed in is null in some
way. Question is, how can I examine this jstring object to see what's in
it? I've tried to find the definition of jstring without luck. Can
anyone help here?

thanks
alex
 
A

Alex Hunsley

Alex said:
I have a JNI problem when calling native code from a java program. The
java program is passing in a non-empty String to the native code, but at
the native code level I crash out on a call to NewStringUTFChars using
the passed-in jstring. When I run with the -Xcheck:jni parameter, I get
the following output:

JVMCI161: FATAL ERROR in native method: JNI received a null string
at a.b.c.MyNativeMethod(Native Method)

(class + package names obscured)

So, it would appear that the jstring getting passed in is null in some
way. Question is, how can I examine this jstring object to see what's in
it? I've tried to find the definition of jstring without luck. Can
anyone help here?

thanks
alex

Aha... jni.h seems to say the jstring is basically a java object
(jobject), so it would appear that I'm to access the jstring via JNI
back through to java, because it is a java String in there? Does that
make sense?

alex
 
A

Alex Hunsley

Alex said:
I have a JNI problem when calling native code from a java program. The
java program is passing in a non-empty String to the native code, but at
the native code level I crash out on a call to NewStringUTFChars using
the passed-in jstring. When I run with the -Xcheck:jni parameter, I get
the following output:

JVMCI161: FATAL ERROR in native method: JNI received a null string
at a.b.c.MyNativeMethod(Native Method)

(class + package names obscured)

So, it would appear that the jstring getting passed in is null in some
way. Question is, how can I examine this jstring object to see what's in
it? I've tried to find the definition of jstring without luck. Can
anyone help here?

thanks
alex

Aha... jni.h seems to say the jstring is basically a java object
(jobject), so it would appear that I'm to access the jstring via JNI
back through to java, because it is a java String in there? Does that
make sense?

alex
 
A

Alex Hunsley

Alex said:
I have a JNI problem when calling native code from a java program. The
java program is passing in a non-empty String to the native code, but at
the native code level I crash out on a call to NewStringUTFChars using
the passed-in jstring. When I run with the -Xcheck:jni parameter, I get
the following output:

JVMCI161: FATAL ERROR in native method: JNI received a null string
at a.b.c.MyNativeMethod(Native Method)

(class + package names obscured)

So, it would appear that the jstring getting passed in is null in some
way. Question is, how can I examine this jstring object to see what's in
it? I've tried to find the definition of jstring without luck. Can
anyone help here?

thanks
alex

Btw, I have checked and the passed in jstring object is not just NULL
either....
In other words, before the calls to NewStringUTFChars, I have the following:

if (jstr == NULL) {
printf("The jstring is null!\n");
}
else {
printf("The jstring is NOT null!\n");
}


.... where jstr is the jstring passed into the native code.
The code prints out "The jstring is NOT null!".

alex
 
C

Chris Uppal

Alex said:
if (jstr == NULL) {
printf("The jstring is null!\n");
}
else {
printf("The jstring is NOT null!\n");
}


... where jstr is the jstring passed into the native code.
The code prints out "The jstring is NOT null!".

This is an extremely remote possibility, and I wouldn't mention it except that
it sounds as if you are getting desperate. I have seen a similar kind of
effect when I've messed up and used DeleteLocalRef() on a reference before I've
finished with it.

BTW, have you tried running this code with the IBM JVM -- I've found that it
tends to be more picky about JNI errors, and better at reporting what's going
wrong. (That's the 1.3 JVM for Windows, I assume other versions are similarly
helpfull).

-- chris
 
A

Alex Hunsley

Chris said:
Alex Hunsley wrote:




This is an extremely remote possibility, and I wouldn't mention it except that
it sounds as if you are getting desperate. I have seen a similar kind of
effect when I've messed up and used DeleteLocalRef() on a reference before I've
finished with it.

In my case, we're not doing anything very complicated at all, nothing to
do with creating references. All I'm doing in the glue layer (in the
native library) is calling CreateStringUTF on some jstrings that are
passed in, calling code somewhere else with the resulting UTF strings,
and then calling ReleaseStringUTFChars.
Nothing more fancy than that, and yet I have this problem! Strange.
BTW, have you tried running this code with the IBM JVM -- I've found that it
tends to be more picky about JNI errors,

The IBM JBM, my friend, is the whole problem. This has to work under IBM
JVM, which I am using, and I'm having these problems. The Sun JVM works
without a hitch for this code.

alex
 
G

Gordon Beaton

All I'm doing in the glue layer (in the native library) is calling
CreateStringUTF on some jstrings that are passed in, calling code
somewhere else with the resulting UTF strings, and then calling
ReleaseStringUTFChars.

That doesn't sound right. Either your description or my understanding
of it is wrong.

AFAIK there is no CreateStringUTF(). Do you mean NewStringUTF(), which
creates a jstring from a char*? If that's the case, you've no business
passing it a jstring in the first place.

Or is it GetStringUTFChars()? That would fit better with the
subsequent call to ReleaseStringUTFChars().

Does the library code you pass the char* to attempt to modify its
contents in any way? Or does it store the pointer and attempt to use
it after you've called ReleaseStringUTFChars()?

Are you calling ReleaseStringUTFChars() unconditionally, or do you
check the contents of the final argument to GetStringUTFChars() first?

Why don't you post a short, complete example? It's a lot easier to
debug real code than your description of it.

/gordon
 
A

Alex Hunsley

Gordon said:
That doesn't sound right. Either your description or my understanding
of it is wrong.

AFAIK there is no CreateStringUTF(). Do you mean NewStringUTF(), which
creates a jstring from a char*? If that's the case, you've no business
passing it a jstring in the first place.

Or is it GetStringUTFChars()? That would fit better with the
subsequent call to ReleaseStringUTFChars().

I beg your pardon, yes, I mean GetStringUTFChars.
Does the library code you pass the char* to attempt to modify its
contents in any way? Or does it store the pointer and attempt to use
it after you've called ReleaseStringUTFChars()?

This is one thing I am looking at, I had stumbled on the idea that the
code may store the pointer to the string somewhere and reuse it later.
I presume that *is* a bad thing, since after ReleaseStringUTFChars is
called, the string pointed to may no longer still be there, this is correct?

Are you calling ReleaseStringUTFChars() unconditionally, or do you
check the contents of the final argument to GetStringUTFChars() first?

No, I'm doing it unconditionally, which is what the docs advise.

Why don't you post a short, complete example? It's a lot easier to
debug real code than your description of it.

I would, but it's not code that I'm allowed to post :(

I've tried to recreate the situation with postable code without any
success as well...

If you see my other thread I started today, it would appear that the
problem is a clash between two native libraries being loaded. It appears
that *any* call to GetStringUTFChars will cause a seg fault, if the call
is inside the native library that was opened 2nd!


thanks
alex
 
C

Chris Uppal

Alex said:
This is one thing I am looking at, I had stumbled on the idea that the
code may store the pointer to the string somewhere and reuse it later.
I presume that *is* a bad thing, since after ReleaseStringUTFChars is
called, the string pointed to may no longer still be there, this is
correct?

You are correct.

Also check that the jstring you are passed has come straight out of Java, that
you haven't accidently stored the reference from some earlier (and now
returned) call from the JVM. (Unlikely that you've done that, but do check.)

An easy way to check your handling of the UTF bytes -- in your first native
method, make a copy of the utf bytes, call ReleaseUTFChars (or whatever it's
called) immediately, and then pass the copy on to your other processing. Do
*not* free() the copy. You'll have a memory leak, but you'll have ensured that
later use of those bytes will be safe. If that "fixes" the problem then you
know that you have to find whatever is making illegal use of the bytes; if not
then you know to look elsewhere.

I've tried to recreate the situation with postable code without any
success as well...

That's encouraging, it makes it very likely that the problem is in you code
(which means you can fix it -- not so easy if the problem's in IBM's code).

-- chris
 
A

Alex Hunsley

Chris said:
Alex Hunsley wrote:




You are correct.

Also check that the jstring you are passed has come straight out of Java, that
you haven't accidently stored the reference from some earlier (and now
returned) call from the JVM. (Unlikely that you've done that, but do check.)

No, I've not done any storing of references like that, my use of JNI is
really quite straightforward simple stuff (good idea though).
An easy way to check your handling of the UTF bytes -- in your first native
method, make a copy of the utf bytes, call ReleaseUTFChars (or whatever it's
called) immediately, and then pass the copy on to your other processing. Do
*not* free() the copy. You'll have a memory leak, but you'll have ensured that
later use of those bytes will be safe. If that "fixes" the problem then you
know that you have to find whatever is making illegal use of the bytes; if not
then you know to look elsewhere.

Yup, I've been along these lines already. I have tried copying the bytes
(by using calloc and then strcpy) that are returned from
GetStringUTFChars (before calling Release) and using those instead; no
luck. Then I tried removing the calls to Release completely (which I
know will leak memory but I'm testing stuff here): still no luck.
And when it falls over, it appear to be on the call to GetStringUTFChars
itself. Something is fishy about the JNI env pointer, perhaps?

Neither native library is being dodgy in any way itself as far as I can
see; but as soon as the code mentions the first one, the second native
library is doomed to fall over.
That's encouraging, it makes it very likely that the problem is in you code
(which means you can fix it -- not so easy if the problem's in IBM's code).

-- chris

Yup, it's opssibly something about our two native libraries, but I have
no idea why they are interacting in this way.

thanks!
alex
 
G

Gordon Beaton

No, I'm doing it unconditionally, which is what the docs advise.

Many examples I've seen show something like this:

jboolean isCopy;
const char *utf = (*env)->GetStringUTFChars(env,str,&isCopy);

...

if (isCopy) {
(*env)->ReleaseStringUTFChars(env,str,utf);
}

I can't see any other use for the "isCopy" argument.
If you see my other thread I started today, it would appear that the
problem is a clash between two native libraries being loaded. It
appears that *any* call to GetStringUTFChars will cause a seg fault,
if the call is inside the native library that was opened 2nd!

Perhaps you have a "traditional" pointer/allocation/buffer error in
one of those libraries and it just happens to show up like this. Have
you tried using a tool like Purify, Electric Fence, Valgrind or
Mpatrol on a purely native application that uses those libraries?

/gordon
 
C

Chris Uppal

Gordon said:
Many examples I've seen show something like this:

jboolean isCopy;
const char *utf = (*env)->GetStringUTFChars(env,str,&isCopy);

...

if (isCopy) {
(*env)->ReleaseStringUTFChars(env,str,utf);
}

I can't see any other use for the "isCopy" argument.

The other idiom is to pass NULL as the third argument to GetStringUTFChars(),
and then ReleaseStringUTFChars() unconditionally. Could Alex's problem be that
he's mixing the two idioms ? ISUBYNK*.

-- chris

[*] It Seems Unlikely But You Never Know -- the constantly-repeated mantra of
the experienced debugger.
 
C

Chris Uppal

Alex said:
Yup, I've been along these lines already. I have tried copying the bytes
(by using calloc and then strcpy) that are returned from
GetStringUTFChars (before calling Release) and using those instead; no
luck.

Unless the problem is the result of random memory corruption (as Gordon Beaton
suggests), that makes it look as the jstring that is passed in is already in
error (somehow) rather than there being something wrong with your Get/Release
of the UTF chars.

What happens if you dummy-out the internals of the two DLLs entirely -- so that
your JNI glue code is the only stuff that's executed ? (I'm assuming that the
two DLLs are both "yours".)

Where does the java.lang.String that's passed to the methods come from in the
first place ? Is it brewed up by normal Java code or is it returned from some
earlier call to your JNI stuff ?

You could try doing a bit of sanity checking by -- say -- using
GetObjectClass() (*and* checking for exceptions) for every reference to a Java
object (not just strings) passed in or out of your JNI code. Be heavy-handed,
check *everything* several times in each method...

You could try ensuring that none of the suspect java.lang.Strings was ever GCed
by doing a NewGlobalRef() on them when you first see them, and then never doing
a corresponding DeleteGlobalRef(). If that "fixed" if then it'd help narrow
down the problem (though it's more likely that NewGlobalRef() will just fail in
the same way as GetStringUTFChars() is doing now ;-(

And when it falls over, it appear to be on the call to GetStringUTFChars
itself. Something is fishy about the JNI env pointer, perhaps?

If you are using the JNIEnv that is provided with the function call, you should
be OK. You say that your JNI stuff is simple, so I assume you are not messing
with threads or creating your own extra JNIEnvs pointers.

-- chris
 
A

Alex Hunsley

Chris said:
Gordon Beaton wrote:

Many examples I've seen show something like this:

jboolean isCopy;
const char *utf = (*env)->GetStringUTFChars(env,str,&isCopy);

...

if (isCopy) {
(*env)->ReleaseStringUTFChars(env,str,utf);
}

I can't see any other use for the "isCopy" argument.


The other idiom is to pass NULL as the third argument to GetStringUTFChars(),
and then ReleaseStringUTFChars() unconditionally. Could Alex's problem be that
he's mixing the two idioms ? ISUBYNK*.

-- chris

[*] It Seems Unlikely But You Never Know -- the constantly-repeated mantra of
the experienced debugger.

Hi to all you respondees
I appear to have solved the problem!
The problem was that I wasn't calling GetStringUTFChars directly, I was
using a helper function, looking like this:

/* helper functions, to aid C/C++ compatability */

char* StubGetStringUTFChars(JNIEnv *theEnv, jstring DDPath, jboolean*
isCopy)
{
#ifdef __cplusplus
/* C++ calling */
return ((char*)theEnv->GetStringUTFChars(DDPath, isCopy));
#else
/* C calling */
return ((char*)(*theEnv)->GetStringUTFChars(theEnv, DDPath, isCopy));
#endif
}

D'oh!
I realised this could be a problem when I started to think about local
references and the scope of returned string data. The JNI docs say that
the results of functions like GetStringUTFChars are only valid in the
scope of the calling function, and once you leave that function, the
returned strings are not guaranteed any more...

So, I removed the helper functions and now call GetStringUTFChars
directly, and hey presto, things work now; I can load the two native
libraries and use them and I don't get seg faults any more.

Thankyou very much x 10 to those of you who have replied to my posts,
it's been very helpful in working ont this problem!

alex
 
C

Chris Uppal

Gordon said:
Many examples I've seen show something like this:

jboolean isCopy;
const char *utf = (*env)->GetStringUTFChars(env,str,&isCopy);

...

if (isCopy) {
(*env)->ReleaseStringUTFChars(env,str,utf);
}

I can't see any other use for the "isCopy" argument.


According to:

http://java.sun.com/docs/books/jni/html/objtypes.html#5161

the call to ReleaseStringUTFChars() is required whether the isCopy is true or
false.

(The isCopy flag indicates whether you can safely modify the returned bytes
in-place.)

-- chris
 
C

Chris Uppal

Alex said:
The JNI docs say that
the results of functions like GetStringUTFChars are only valid in the
scope of the calling function, and once you leave that function, the
returned strings are not guaranteed any more...

Where did you find that ? I've never seen that condition in the JNI docs I've
read, and I've just rechecked the spec, and the JNI book on Sun's website.

I'm glad it's working for you, though.

-- chris
 

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
474,444
Messages
2,571,710
Members
48,796
Latest member
Greg L.
Top