Java 9 build 148 causes trouble in Apache Lucene/Solr/Elasticsearch
Peter Levart
peter.levart at gmail.com
Sun Dec 11 20:31:45 UTC 2016
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.levart at gmail.com]
> *Sent:* Saturday, December 10, 2016 10:23 PM
> *To:* Uwe Schindler <uschindler at apache.org>; Chris Hegarty
> <chris.hegarty at oracle.com>
> *Cc:* jigsaw-dev at openjdk.java.net; Core-Libs-Dev
> <core-libs-dev at 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.levart at gmail.com> <mailto:peter.levart at 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
>
More information about the jigsaw-dev
mailing list