JNI ReleasePrimitiveArrayCritical with mode JNI_COMMIT shouldn't end critical region
David Holmes
david.holmes at oracle.com
Thu Dec 7 05:00:54 UTC 2017
On 7/12/2017 2:55 PM, Ian Rogers wrote:
> Thanks, fwiw Jikes RVM agrees that all critical releases end the
> critical region:
> https://github.com/JikesRVM/JikesRVM/blob/master/rvm/src/org/jikesrvm/jni/JNIFunctions.java#L5936
>
> As does Cacao:
> http://mips.complang.tuwien.ac.at/hg/cacao/file/2b4c9b6c245d/src/native/jni.cpp#l3208
>
> Kaffe (with a non-moving GC) treats the release in the same way as
> Release<Primitive>ArrayElements:
> https://github.com/kaffe/kaffe/blob/master/kaffe/kaffevm/jni/jni-arrays.c#L404
> which is the same as how it is handled on Android.
>
> HotSpot has managed to put a foot in both camps, ending the critical
> always (a la Jikes RVM and Cacao) but honoring commit behavior (and
> leaking) when in -Xcheck:jni.
So ... I should file a bug for the leak in the checked version and apply
your suggested patch to always pass mode 0?
Thanks,
David
> Thanks,
> Ian
>
> On Wed, Dec 6, 2017 at 5:25 PM, David Holmes <david.holmes at oracle.com
> <mailto:david.holmes at oracle.com>> wrote:
>
> Hi Ian,
>
> On 7/12/2017 4:48 AM, Ian Rogers wrote:
>
> Thanks David, I think we may have differing opinions on clarity
> :-) In the case of -Xcheck:jni and with HotSpot a copy is always
> made, and so
>
>
> Ah I see. I was considering only the "real" functionality.
>
> The fact the checked version of getPrimitiveArrayCritical creates a
> copy seems to be treated as an internal detail as it does not AFAICS
> report that a copy was in fact made - the passed in isCopy pointer
> will be set false by the real getPrimitiveArrayCritical.
>
> perhaps the attached patch causes the implementation to match
> the spec.
>
>
> The whole logic surrounding the management of the copy seems
> somewhat suspect to me. As you note with your patch
> check_wrapped_array_release honours the mode, which in the checked
> case allows, AFAICS, the internally made copy to "leak". So ignoring
> the passed in mode and always passing 0 to
> check_wrapped_array_release seems more correct.
>
> Given that commit doesn't free a copy, is it intended behavior
> that in HotSpot it ends a critical region? ie In a VM that
> allowed copies you could imagine, Get, Commit, Release and as
> spec-ed the critical region ends at the commit if not a copy,
> and at the release if it is. Perhaps the simplest thing is to
> remove the notion of commit here.
>
>
> I honestly do not know what this API is really trying to achieve in
> that regard. I don't know the intended usage of "commit" mode. Why
> would you not free the copied buffer? The spec unhelpfully only states:
>
> "The other options give the programmer more control over memory
> management and should be used with extreme care."
>
> And if you don't free it what can you do with it? For
> Get*ArrayElements it clearly states
>
> "The result is valid until the corresponding
> Release<PrimitiveType>ArrayElements() function is called."
>
> so once any Release* is done, regardless of mode, it would seem the
> array (copy or not) is no longer valid and should not be accessed
> again. So I don't see any expectation that you can call Release*
> multiple times and so in terms of the critical variants I expect the
> critical section to end when Release is called - regardless of mode.
>
> David
>
> Thanks,
> Ian
>
>
> On Tue, Dec 5, 2017 at 4:37 PM, David Holmes
> <david.holmes at oracle.com <mailto:david.holmes at oracle.com>
> <mailto:david.holmes at oracle.com
> <mailto:david.holmes at oracle.com>>> wrote:
>
> Hi Ian,
>
> On 6/12/2017 9:15 AM, Ian Rogers wrote:
>
> From:
> https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetPrimitiveArrayCritical_ReleasePrimitiveArrayCritical
> <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetPrimitiveArrayCritical_ReleasePrimitiveArrayCritical>
>
> <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetPrimitiveArrayCritical_ReleasePrimitiveArrayCritical
> <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetPrimitiveArrayCritical_ReleasePrimitiveArrayCritical>>
>
>
> You need to see the updated spec:
>
> https://docs.oracle.com/javase/9/docs/specs/jni/functions.html#getprimitivearraycritical-releaseprimitivearraycritical
> <https://docs.oracle.com/javase/9/docs/specs/jni/functions.html#getprimitivearraycritical-releaseprimitivearraycritical>
>
> <https://docs.oracle.com/javase/9/docs/specs/jni/functions.html#getprimitivearraycritical-releaseprimitivearraycritical
> <https://docs.oracle.com/javase/9/docs/specs/jni/functions.html#getprimitivearraycritical-releaseprimitivearraycritical>>
>
> That spec makes it clear:
>
> "mode: the release mode (see Primitive Array Release Modes): 0,
> JNI_COMMIT or JNI_ABORT. Ignored if carray was a not copy."
>
> In hotspot getCriticalArrayPrimitive never returns a copy
> so the
> mode is always ignored, as per the existing comment.
>
> David
> -----
>
>
> "The semantics of these two functions are very similar
> to the
> existing
> Get/Release<primitivetype>ArrayElements functions. "
>
> https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#Release_PrimitiveType_ArrayElements_routines
> <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#Release_PrimitiveType_ArrayElements_routines>
>
> <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#Release_PrimitiveType_ArrayElements_routines
> <https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#Release_PrimitiveType_ArrayElements_routines>>
>
> "JNI_COMMIT copy back the content but do not free the
> elems buffer"
>
> Consider the pattern of:
> GetPrimitiveArrayCritical(...)
> ReleasePrimitiveArrayCritical(..., JNI_COMMIT)
> ReleasePrimitiveArrayCritical(..., 0)
>
> where the first release is to just achieve a copy back.
> For example,
> jniCheck.cpp will copy back but not free a copy in the
> case of
> JNI_COMMIT
> for a critical. The implementation of
> ReleasePrimitiveArrayCritical ignores
> all arguments and so it ends the critical region even
> in the
> event of a
> commit.
>
> The attached patch makes ReleasePrimitiveArrayCritical
> consider
> the mode
> argument when releasing the GCLocker.
>
> Thanks,
> Ian
>
>
>
More information about the hotspot-dev
mailing list