Pedantic JNI question

B

Bill Medland

I'm just trying to do the job properly and the correct answer is not obvious
to me in the documentation.

a-If I call GetByteArrayRegion I should later call ReleaseByteArrayRegion.
b-If an exception is thrown then the only functions that it is safe to call
are ExceptionCheck(I presume, but the docs don't say so), ExceptionClear,
ExceptionDescribe and ExceptionOccurred.

So does that mean in the event of an exception we can return safely without
bothering with the ReleaseByteArrayRegion calls (and the system will tidy
up).
 
D

David Lee Lambert

I'm just trying to do the job properly and the correct answer is not obvious
to me in the documentation.

a-If I call GetByteArrayRegion I should later call ReleaseByteArrayRegion.
b-If an exception is thrown then the only functions that it is safe to call
are ExceptionCheck(I presume, but the docs don't say so), ExceptionClear,
ExceptionDescribe and ExceptionOccurred.

So does that mean in the event of an exception we can return safely without
bothering with the ReleaseByteArrayRegion calls (and the system will tidy
up).

There is no ReleaseByteArrayRegion call in the JNI spec. Did you mean
ReleaseByteArrayElements?

Anyway, according to the way I read the spec, the statement that "When
there is a pending exception, the only JNI functions that are safe to call
are..." means just what it says. In general the JVM cleans up dangling
references upon return from a native function. It could be argued that
the native-type-array pointers returned by
Get<type>ArrayElements, GetStringChars and GetStringUTFChars are not local
references, so I always clean them up if possible; but I'm not sure
exactly what different JVMs do.

If you want to do some cleanup that requires calls into the JVM, you have
an alternative: store the "jthrowable" returned by ExceptionOccurred
somewhere; call ExceptionClear; make your calls; call Throw with the
"jthrowable" you stored before you return from the native function.
 
B

Bill Medland

David said:
There is no ReleaseByteArrayRegion call in the JNI spec. Did you mean
ReleaseByteArrayElements?

Woops, Yes - I meant Elements, not Region, of course.
Anyway, according to the way I read the spec, the statement that "When
there is a pending exception, the only JNI functions that are safe to call
are..." means just what it says. In general the JVM cleans up dangling
references upon return from a native function. It could be argued that
the native-type-array pointers returned by
Get<type>ArrayElements, GetStringChars and GetStringUTFChars are not local
references, so I always clean them up if possible; but I'm not sure
exactly what different JVMs do.

If you want to do some cleanup that requires calls into the JVM, you have
an alternative: store the "jthrowable" returned by ExceptionOccurred
somewhere; call ExceptionClear; make your calls; call Throw with the
"jthrowable" you stored before you return from the native function.

Thanks for your input, David.

I guess I'll just leave the "references" dangling around; I am not going to
start messing about putting exceptions away for a moment, unwinding,
reinstating the exception, handling the possibility that reinstating the
exception fails, etc.
I'm sure they thought about it when they designed the system; I just wish
they'd documented their conclusions.
 
C

Chris Uppal

Bill said:
I guess I'll just leave the "references" dangling around; I am not going
to start messing about putting exceptions away for a moment, unwinding,
reinstating the exception, handling the possibility that reinstating the
exception fails, etc.
I'm sure they thought about it when they designed the system; I just wish
they'd documented their conclusions.

I think that's a very bad idea. There is no reason at all (that I know of) to
suppose that it is intended to be safe to leave those "byte-array-regions"
unreleased. The documentation, as you've noted, contains no hint that that is
allowed. Also, I can see no sensible reason why the JNI people would put time
and effort into automatic reclaimation of byte-array-regions which only worked
in the error case -- I can just about imagine them wanting[*] to arrange for
automatic reclaimation (similar to reclaiming local references), but if so then
it would surely work in the main-line case, not just the exceptional one.

-- chris

[*] I can imagine them wanting to arrange that, but I find it a lot harder to
imagine a practical implementation.
 
B

Bill Medland

Chris said:
I think that's a very bad idea. There is no reason at all (that I know
of) to suppose that it is intended to be safe to leave those
"byte-array-regions"
unreleased.

"because we thought of that and it won't be a problem; we can define a good
api that won't make the programmer jump through hoops just to write robust
code; after all, we are professional programmers and we would want to write
robust code so lets assume the users of our api will too"
The documentation, as you've noted, contains no hint that
that is
allowed. Also, I can see no sensible reason why the JNI people would put
time and effort into automatic reclaimation of byte-array-regions which
only worked in the error case -- I can just about imagine them wanting[*]
to arrange for automatic reclaimation (similar to reclaiming local
references), but if so then it would surely work in the main-line case,
not just the exceptional one.

Ah well, whoever said life was easy. I suppose I'll have to bite on the
bullet. No wonder there is a tendency not to look at the return code and
simply do what seems to work often enough.
-- chris

[*] I can imagine them wanting to arrange that, but I find it a lot harder
[to
imagine a practical implementation.
 
C

Chris Uppal

Bill Medland wrote:

[me:]
"because we thought of that and it won't be a problem; we can define a
good api that won't make the programmer jump through hoops just to write
robust code; after all, we are professional programmers and we would want
to write robust code so lets assume the users of our api will too"

<grin/>

I think Sun's position is that if you want that kind of thing then you should
be using Java, not C ;-)

-- chris
 
B

Bill Medland

Chris said:
Bill Medland wrote:

[me:]
"because we thought of that and it won't be a problem; we can define a
good api that won't make the programmer jump through hoops just to write
robust code; after all, we are professional programmers and we would want
to write robust code so lets assume the users of our api will too"

<grin/>

I think Sun's position is that if you want that kind of thing then you
should be using Java, not C ;-)

-- chris
Yeh. Anyway, thanks for the reality check, Chris.
 
B

Bill Medland

Bill said:
Woops, Yes - I meant Elements, not Region, of course.


Thanks for your input, David.

I guess I'll just leave the "references" dangling around; I am not going
to start messing about putting exceptions away for a moment, unwinding,
reinstating the exception, handling the possibility that reinstating the
exception fails, etc.
I'm sure they thought about it when they designed the system; I just wish
they'd documented their conclusions.

Latest news. They(/he) did. So that just muddies the water even further.
In Sheng Liang's "Programmer's Guide and Specification" his section 11.8.2
lists a much larger selection of functions that are safe to call while
there is an exception pending, including Release<Type>ArrayElements.

So who do you believe? The author of the design or the documentation that
comes with the product.

Seeing as Sheng Liang actually includes ExceptionCheck in his list, which
the documentation doesn't, and seeing as how I am less than impressed with
Sun's quality on some other things I think it is actually more reasonable
to go with his specification than the one that comes with the Sun Java
product (what a thing to have to say!).

So I am going to assume that it is safe to call
Release<Type>ArrayElements(...JNI_ABORT) with there being an exception
current and that it will not overwrite the exception.
 
C

Chris Uppal

Bill said:
Latest news. They(/he) did. So that just muddies the water even further.
In Sheng Liang's "Programmer's Guide and Specification" his section 11.8.2
lists a much larger selection of functions that are safe to call while
there is an exception pending, including Release<Type>ArrayElements.

Ah! Good.

So who do you believe? The author of the design or the documentation that
comes with the product.

I would believe whichever seemed most plausible ;-)

I'd prefer to believe the spec, and certainly I would take the spec over Liang
if there was a chance that Liang was simplifying (or even being mildly
inaccurate) for the sake of exposition. But in a case like this where they
flat-out contradict each other, and where the spec is obviously
wrong/incomplete anyway (missing ExceptionCheck(), as you say), I would take
Liang. After all Liang's stuff was written after, and presumably in full
knowledge of, the spec.

BTW, I found the thing about it being improper to DeleteLocalRef() with the
wrong JNIEnv. It wasn't quite what or where I remembered it (though it has the
same effect on my code). In /Liang's/ version of the spec, the second
paragraph of the text for that function states

Deleting a local reference that does not belong to the topmost
local reference frame is a no-op. Each native method invocation
creates a new local reference frame. The PushLocalFrame
function (added in Java 2 SDK release 1.2) also creates a new
local reference frame.

So it isn't actually an /error/ as such, although it doesn't do what one might
expect. There is (irritatingly) no equivalent to that paragraph in the version
of the JNI spec which comes with JDK 1.4 or 1.5...

-- chris
 
B

Bill Medland

Chris said:
BTW, I found the thing about it being improper to DeleteLocalRef() with
the
wrong JNIEnv. It wasn't quite what or where I remembered it (though it
has the
same effect on my code). In /Liang's/ version of the spec, the second
paragraph of the text for that function states

Deleting a local reference that does not belong to the topmost
local reference frame is a no-op. Each native method invocation
creates a new local reference frame. The PushLocalFrame
function (added in Java 2 SDK release 1.2) also creates a new
local reference frame.

So it isn't actually an /error/ as such, although it doesn't do what one
might
expect. There is (irritatingly) no equivalent to that paragraph in the
version of the JNI spec which comes with JDK 1.4 or 1.5...

-- chris
Well that was a little brain-dead, wasn't it :)
So that means if I have a library function that carefully deletes all the
local references it creates I still have to keep track of how many
references there were because if Push/PopLocalFrame is called it needs to
allow for all those references that won't actually be deleted after all.
(What's the smiley for "shakes head in total resignation?")
 
C

Chris Uppal

Bill said:
Well that was a little brain-dead, wasn't it :)
So that means if I have a library function that carefully deletes all the
local references it creates I still have to keep track of how many
references there were because if Push/PopLocalFrame is called it needs to
allow for all those references that won't actually be deleted after all.

That is why my stuff (if run in a mode where there can possibly be more than
one JNIEnv/local frame active) now converts /all/ local references to globals
as soon as it sees them, and at the lowest level of the housekeeping code. I
tried a few more "clever" approaches (stacks of JNIEnvs and so on) before
deciding they were all too difficult to make right, and fell back to good old
brute force.

Not very nice, really...

-- 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
473,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top