Hi Uwe,

On 12/11/2016 01:57 PM, Uwe Schindler wrote:

Hi,

How about the following:

-Check that the buffer is direct, if not throw IAE(“not direct buffer”)

-Check that buffer has attachment==null (this tells you that it’s not a slice/dup), if not throw IAE(“not allowed to free duplicates/slices”)

-Finally do the standard if (cleaner!=null) cleaner.clean(), but don’t throw any exceptions if cleaner is null (as this is implementation detail)

This allows for empty buffers without cleaner that are still marked as direct. But it disallows all slices or duplicates.


Yes, this would be the right logic I agree. It would silently ignore the requests to free memory for buffers constructed via JNI's NewDirectByteBuffer calls, but I suppose this would not be a problem in practice.

I am fine with Alan’s proposal to restrict to MappedByteBuffer but that’s out of my interest – I am happy to unmap mapped byte buffers. I would also place the method in the legacy sun.misc.Unsafe only, the JDK-internal private one is not accessible to the outside. Of course for consistency it could be in both, but primarily it must be in sun.misc.Unsafe – that’s also what most code is using anyways.


Yes, internally, at least in java.base, the code can always directly invoke the DirectBuffer's and Cleaner's methods...

Regards, Peter


Uwe

*From:*Peter Levart [mailto:peter.lev...@gmail.com]
*Sent:* Saturday, December 10, 2016 10:23 PM
*To:* Uwe Schindler <uschind...@apache.org>; Chris Hegarty <chris.hega...@oracle.com> *Cc:* jigsaw-dev@openjdk.java.net; Core-Libs-Dev <core-libs-...@openjdk.java.net> *Subject:* Re: Java 9 build 148 causes trouble in Apache Lucene/Solr/Elasticsearch

On 12/10/2016 09:00 PM, Uwe Schindler wrote:

    Hi,

    We noticed that buffers with zero length also have no cleaner.
    This is why we also have the null check in our code (see Github)
    and the guardWithTest in the MethodHandle, although we never free
    duplicates. So a noop is better imho.


Oh yes, good catch. Then what about being noop just for zero length? I don't know, maybe I'm just being paranoid and those who would use this API know perfectly well what they are doing. I'm just imagining a situation where one would create and keep just a duplicate of a direct buffer and afterwards use it to try to deallocate the native memory. This would be a noop, but the developer would think it works as GC would finally do it for him. I think it's better to throw an exception to prevent such situations...

Regards, Peter



    I like the Unsafe approach. To me both variants are fine.

    Uwe

    Am 10. Dezember 2016 20:47:46 MEZ schrieb Peter Levart
    <peter.lev...@gmail.com> <mailto:peter.lev...@gmail.com>:

        Hi Chris,

        On 12/10/2016 06:11 PM, Chris Hegarty wrote:

            How about: Unsafe::deallocate(ByteBuffer directBuffer)?

               http://cr.openjdk.java.net/~chegar/Unsafe_deallocate/
            <http://cr.openjdk.java.net/%7Echegar/Unsafe_deallocate/>


        Apart from the fact that Unsafe is (was?) reserved for
        low-level stuff, I think this approach is reasonable. Is the
        method in jdk.internal.misc.Unsafe needed? You could add the
        method just to the sun.misc.Unsafe (to keep internal Unsafe
        free from hacks) and export the two packages selectively to
        jdk.unsupported.


            We could attempt to limit this to the direct buffer that "owns" the

            memory, i.e. not a duplicate or a slice, but I'm not sure it is 
worth

            it.


        What you have here *is* limited to direct ByteBuffer(s) that
        "own" the memory. Derived buffer(s) (duplicated or sliced) do
        not have a Cleaner instance (they have an 'attachment' to keep
        the 1st-level buffer reachable while they are reachable). I
        would even make it more unforgiving by throwing an IAE if the
        passed-in buffer didn't have a Cleaner. In addition I would
        specify this behavior. For example:

        "Deallocates the underlying memory associated with given
        directBuffer if the buffer was obtained from either {@link
        ByteBuffer#allocateDirect} or {@link FileChannel#map} methods.
        In any other case (when the buffer is not a direct buffer or
        was obtained by  {@link ByteBuffer#duplicate() duplicating} or
        {@link ByteBuffer#slice(int, int) slicing} a direct buffer),
        the method throws {@code IllegalArgumentException}.

        Regards, Peter


Reply via email to