1 /*
  2  *  Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
  3  *  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  *  This code is free software; you can redistribute it and/or modify it
  6  *  under the terms of the GNU General Public License version 2 only, as
  7  *  published by the Free Software Foundation.  Oracle designates this
  8  *  particular file as subject to the "Classpath" exception as provided
  9  *  by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  *  This code is distributed in the hope that it will be useful, but WITHOUT
 12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 
 27 package jdk.incubator.foreign;
 28 
 29 import java.nio.ByteBuffer;
 30 
 31 import jdk.internal.foreign.AbstractMemorySegmentImpl;
 32 import jdk.internal.foreign.HeapMemorySegmentImpl;
 33 import jdk.internal.foreign.MappedMemorySegmentImpl;
 34 import jdk.internal.foreign.MemoryAddressImpl;
 35 import jdk.internal.foreign.NativeMemorySegmentImpl;
 36 import jdk.internal.foreign.Utils;
 37 
 38 import java.io.IOException;
 39 import java.nio.channels.FileChannel;
 40 import java.nio.file.Path;
 41 import java.util.Objects;
 42 import java.util.Spliterator;
 43 import java.util.function.Consumer;
 44 
 45 /**
 46  * A memory segment models a contiguous region of memory. A memory segment is associated with both spatial
 47  * and temporal bounds. Spatial bounds ensure that memory access operations on a memory segment cannot affect a memory location
 48  * which falls <em>outside</em> the boundaries of the memory segment being accessed. Temporal checks ensure that memory access
 49  * operations on a segment cannot occur after a memory segment has been closed (see {@link MemorySegment#close()}).
 50  * <p>
 51  * All implementations of this interface must be <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>;
 52  * use of identity-sensitive operations (including reference equality ({@code ==}), identity hash code, or synchronization) on
 53  * instances of {@code MemorySegment} may have unpredictable results and should be avoided. The {@code equals} method should
 54  * be used for comparisons.
 55  * <p>
 56  * Non-platform classes should not implement {@linkplain MemorySegment} directly.
 57  *
 58  * <h2>Constructing memory segments from different sources</h2>
 59  *
 60  * There are multiple ways to obtain a memory segment. First, memory segments backed by off-heap memory can
 61  * be allocated using one of the many factory methods provided (see {@link MemorySegment#allocateNative(MemoryLayout)},
 62  * {@link MemorySegment#allocateNative(long)} and {@link MemorySegment#allocateNative(long, long)}). Memory segments obtained
 63  * in this way are called <em>native memory segments</em>.
 64  * <p>
 65  * It is also possible to obtain a memory segment backed by an existing heap-allocated Java array,
 66  * using one of the provided factory methods (e.g. {@link MemorySegment#ofArray(int[])}). Memory segments obtained
 67  * in this way are called <em>array memory segments</em>.
 68  * <p>
 69  * It is possible to obtain a memory segment backed by an existing Java byte buffer (see {@link ByteBuffer}),
 70  * using the factory method {@link MemorySegment#ofByteBuffer(ByteBuffer)}.
 71  * Memory segments obtained in this way are called <em>buffer memory segments</em>. Note that buffer memory segments might
 72  * be backed by native memory (as in the case of native memory segments) or heap memory (as in the case of array memory segments),
 73  * depending on the characteristics of the byte buffer instance the segment is associated with. For instance, a buffer memory
 74  * segment obtained from a byte buffer created with the {@link ByteBuffer#allocateDirect(int)} method will be backed
 75  * by native memory.
 76  * <p>
 77  * Finally, it is also possible to obtain a memory segment backed by a memory-mapped file using the factory method
 78  * {@link MemorySegment#mapFromPath(Path, long, FileChannel.MapMode)}. Such memory segments are called <em>mapped memory segments</em>
 79  * (see {@link MappedMemorySegment}).
 80  *
 81  * <h2>Closing a memory segment</h2>
 82  *
 83  * Memory segments are closed explicitly (see {@link MemorySegment#close()}). In general when a segment is closed, all off-heap
 84  * resources associated with it are released; this has different meanings depending on the kind of memory segment being
 85  * considered:
 86  * <ul>
 87  *     <li>closing a native memory segment results in <em>freeing</em> the native memory associated with it</li>
 88  *     <li>closing a mapped memory segment results in the backing memory-mapped file to be unmapped</li>
 89  *     <li>closing a buffer, or a heap segment does not have any side-effect, other than marking the segment
 90  *     as <em>not alive</em> (see {@link MemorySegment#isAlive()}). Also, since the buffer and heap segments might keep
 91  *     strong references to the original buffer or array instance, it is the responsibility of clients to ensure that
 92  *     these segments are discarded in a timely manner, so as not to prevent garbage collection to reclaim the underlying
 93  *     objects.</li>
 94  * </ul>
 95  *
 96  * <h2><a id = "thread-confinement">Thread confinement</a></h2>
 97  *
 98  * Memory segments support strong thread-confinement guarantees. Upon creation, they are assigned an <em>owner thread</em>,
 99  * typically the thread which initiated the creation operation. After creation, only the owner thread will be allowed
100  * to directly manipulate the memory segment (e.g. close the memory segment) or access the underlying memory associated with
101  * the segment using a memory access var handle. Any attempt to perform such operations from a thread other than the
102  * owner thread will result in a runtime failure.
103  * <p>
104  * Memory segments support <em>serial thread confinement</em>; that is, ownership of a memory segment can change (see
105  * {@link #withOwnerThread(Thread)}). This allows, for instance, for two threads {@code A} and {@code B} to share
106  * a segment in a controlled, cooperative and race-free fashion.
107  * <p>
108  * In some cases, it might be useful for multiple threads to process the contents of the same memory segment concurrently
109  * (e.g. in the case of parallel processing); while memory segments provide strong confinement guarantees, it is possible
110  * to obtain a {@link Spliterator} from a segment, which can be used to slice the segment and allow multiple thread to
111  * work in parallel on disjoint segment slices (this assumes that the access mode {@link #ACQUIRE} is set).
112  * For instance, the following code can be used to sum all int values in a memory segment in parallel:
113  * <blockquote><pre>{@code
114 SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.ofSequence(1024, MemoryLayouts.JAVA_INT);
115 VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
116 int sum = StreamSupport.stream(segment.spliterator(SEQUENCE_LAYOUT), true)
117             .mapToInt(segment -> (int)VH_int.get(segment.baseAddress))
118             .sum();
119  * }</pre></blockquote>
120  *
121  * <h2><a id = "access-modes">Access modes</a></h2>
122  *
123  * Memory segments supports zero or more <em>access modes</em>. Supported access modes are {@link #READ},
124  * {@link #WRITE}, {@link #CLOSE} and {@link #ACQUIRE}. The set of access modes supported by a segment alters the
125  * set of operations that are supported by that segment. For instance, attempting to call {@link #close()} on
126  * a segment which does not support the {@link #CLOSE} access mode will result in an exception.
127  * <p>
128  * The set of supported access modes can only be made stricter (by supporting <em>less</em> access modes). This means
129  * that restricting the set of access modes supported by a segment before sharing it with other clients
130  * is generally a good practice if the creator of the segment wants to retain some control over how the segment
131  * is going to be accessed.
132  *
133  * <h2>Memory segment views</h2>
134  *
135  * Memory segments support <em>views</em>. For instance, it is possible to alter the set of supported access modes,
136  * by creating an <em>immutable</em> view of a memory segment, as follows:
137  * <blockquote><pre>{@code
138 MemorySegment segment = ...
139 MemorySegment roSegment = segment.withAccessModes(segment.accessModes() & ~WRITE);
140  * }</pre></blockquote>
141  * It is also possible to create views whose spatial bounds are stricter than the ones of the original segment
142  * (see {@link MemorySegment#asSlice(long, long)}).
143  * <p>
144  * Temporal bounds of the original segment are inherited by the view; that is, closing a segment view, such as a sliced
145  * view, will cause the original segment to be closed; as such special care must be taken when sharing views
146  * between multiple clients. If a client want to protect itself against early closure of a segment by
147  * another actor, it is the responsibility of that client to take protective measures, such as removing {@link #CLOSE}
148  * from the set of supported access modes, before sharing the view with another client.
149  * <p>
150  * To allow for interoperability with existing code, a byte buffer view can be obtained from a memory segment
151  * (see {@link #asByteBuffer()}). This can be useful, for instance, for those clients that want to keep using the
152  * {@link ByteBuffer} API, but need to operate on large memory segments. Byte buffers obtained in such a way support
153  * the same spatial and temporal access restrictions associated to the memory address from which they originated.
154  *
155  * @apiNote In the future, if the Java language permits, {@link MemorySegment}
156  * may become a {@code sealed} interface, which would prohibit subclassing except by
157  * {@link MappedMemorySegment} and other explicitly permitted subtypes.
158  *
159  * @implSpec
160  * Implementations of this interface are immutable and thread-safe.
161  */
162 public interface MemorySegment extends AutoCloseable {
163 
164     /**
165      * The base memory address associated with this memory segment. The returned address is
166      * a <em>checked</em> memory address and can therefore be used in derefrence operations
167      * (see {@link MemoryAddress}).
168      * @return The base memory address.
169      */
170     MemoryAddress baseAddress();
171 
172     /**
173      * Returns a spliterator for the given memory segment. The returned spliterator reports {@link Spliterator#SIZED},
174      * {@link Spliterator#SUBSIZED}, {@link Spliterator#IMMUTABLE}, {@link Spliterator#NONNULL} and {@link Spliterator#ORDERED}
175      * characteristics.
176      * <p>
177      * The returned spliterator splits the segment according to the specified sequence layout; that is,
178      * if the supplied layout is a sequence layout whose element count is {@code N}, then calling {@link Spliterator#trySplit()}
179      * will result in a spliterator serving approximatively {@code N/2} elements (depending on whether N is even or not).
180      * As such, splitting is possible as long as {@code N >= 2}.
181      * <p>
182      * The returned spliterator effectively allows to slice a segment into disjoint sub-segments, which can then
183      * be processed in parallel by multiple threads (if the access mode {@link #ACQUIRE} is set).
184      * While closing the segment (see {@link #close()}) during pending concurrent execution will generally
185      * fail with an exception, it is possible to close a segment when a spliterator has been obtained but no thread
186      * is actively working on it using {@link Spliterator#tryAdvance(Consumer)}; in such cases, any subsequent call
187      * to {@link Spliterator#tryAdvance(Consumer)} will fail with an exception.
188      * @param segment the segment to be used for splitting.
189      * @param layout the layout to be used for splitting.
190      * @param <S> the memory segment type
191      * @return the element spliterator for this segment
192      * @throws IllegalStateException if the segment is not <em>alive</em>, or if access occurs from a thread other than the
193      * thread owning this segment
194      */
195     static <S extends MemorySegment> Spliterator<S> spliterator(S segment, SequenceLayout layout) {
196         return AbstractMemorySegmentImpl.spliterator(segment, layout);
197     }
198 
199     /**
200      * The thread owning this segment.
201      * @return the thread owning this segment.
202      */
203     Thread ownerThread();
204 
205     /**
206      * Obtains a new memory segment backed by the same underlying memory region as this segment,
207      * but with different owner thread. As a side-effect, this segment will be marked as <em>not alive</em>,
208      * and subsequent operations on this segment will result in runtime errors.
209      * <p>
210      * Write accesses to the segment's content <a href="../../../java/util/concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
211      * hand-over from the current owner thread to the new owner thread, which in turn <i>happens before</i> read accesses to the segment's contents on
212      * the new owner thread.
213      *
214      * @param newOwner the new owner thread.
215      * @return a new memory segment backed by the same underlying memory region as this segment,
216      *      owned by {@code newOwner}.
217      * @throws IllegalStateException if this segment is not <em>alive</em>, or if access occurs from a thread other than the
218      * thread owning this segment, or if the segment cannot be closed because it is being operated upon by a different
219      * thread (see {@link #spliterator(SequenceLayout)}).
220      * @throws NullPointerException if {@code newOwner == null}
221      * @throws IllegalArgumentException if the segment is already a confined segment owner by {@code newOnwer}.
222      * @throws UnsupportedOperationException if this segment does not support the {@link #HANDOFF} access mode.
223      */
224     MemorySegment withOwnerThread(Thread newOwner);
225 
226     /**
227      * The size (in bytes) of this memory segment.
228      * @return The size (in bytes) of this memory segment.
229      */
230     long byteSize();
231 
232     /**
233      * Obtains a segment view with specific <a href="#access-modes">access modes</a>. Supported access modes are {@link #READ}, {@link #WRITE},
234      * {@link #CLOSE} and {@link #ACQUIRE}. It is generally not possible to go from a segment with stricter access modes
235      * to one with less strict access modes. For instance, attempting to add {@link #WRITE} access mode to a read-only segment
236      * will be met with an exception.
237      * @param accessModes an ORed mask of zero or more access modes.
238      * @return a segment view with specific access modes.
239      * @throws UnsupportedOperationException when {@code mask} is an access mask which is less strict than the one supported by this
240      * segment.
241      */
242     MemorySegment withAccessModes(int accessModes);
243 
244     /**
245      * Does this segment support a given set of access modes?
246      * @param accessModes an ORed mask of zero or more access modes.
247      * @return true, if the access modes in {@code accessModes} are stricter than the ones supported by this segment.
248      */
249     boolean hasAccessModes(int accessModes);
250 
251     /**
252      * Returns the <a href="#access-modes">access modes</a> associated with this segment; the result is represented as ORed values from
253      * {@link #READ}, {@link #WRITE}, {@link #CLOSE} and {@link #ACQUIRE}.
254      * @return the access modes associated with this segment.
255      */
256     int accessModes();
257 
258     /**
259      * Obtains a new memory segment view whose base address is the same as the base address of this segment plus a given offset,
260      * and whose new size is specified by the given argument.
261      * @param offset The new segment base offset (relative to the current segment base address), specified in bytes.
262      * @param newSize The new segment size, specified in bytes.
263      * @return a new memory segment view with updated base/limit addresses.
264      * @throws IndexOutOfBoundsException if {@code offset < 0}, {@code offset > byteSize()}, {@code newSize < 0}, or {@code newSize > byteSize() - offset}
265      */
266     MemorySegment asSlice(long offset, long newSize);
267 
268     /**
269      * Is this segment alive?
270      * @return true, if the segment is alive.
271      * @see MemorySegment#close()
272      */
273     boolean isAlive();
274 
275     /**
276      * Closes this memory segment. Once a memory segment has been closed, any attempt to use the memory segment,
277      * or to access the memory associated with the segment will fail with {@link IllegalStateException}. Depending on
278      * the kind of memory segment being closed, calling this method further trigger deallocation of all the resources
279      * associated with the memory segment.
280      * @throws IllegalStateException if this segment is not <em>alive</em>, or if access occurs from a thread other than the
281      * thread owning this segment, or if the segment cannot be closed because it is being operated upon by a different
282      * thread (see {@link #spliterator(MemorySegment, SequenceLayout)}).
283      * @throws UnsupportedOperationException if this segment does not support the {@link #CLOSE} access mode.
284      */
285     void close();
286 
287     /**
288      * Fills a value into this memory segment.
289      * <p>
290      * More specifically, the given value is filled into each address of this
291      * segment. Equivalent to (but likely more efficient than) the following code:
292      *
293      * <blockquote><pre>
294      * byteHandle = MemoryLayout.ofSequence(MemoryLayouts.JAVA_BYTE)
295      *         .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
296      * for (long l = 0; l < segment.byteSize(); l++) {
297      *     byteHandle.set(segment.baseAddress(), l, value);
298      * }</pre></blockquote>
299      * without any regard or guarantees on the ordering of particular memory
300      * elements being set.
301      * <p>
302      * Fill can be useful to initialize or reset the memory of a segment.
303      *
304      * @param value the value to fill into this segment
305      * @return this memory segment
306      * @throws IllegalStateException if this segment is not <em>alive</em>, or if access occurs from a thread other than the
307      * thread owning this segment
308      * @throws UnsupportedOperationException if this segment does not support the {@link #WRITE} access mode
309      */
310     MemorySegment fill(byte value);
311 
312     /**
313      * Perform bulk copy from given source segment to this segment. More specifically, the bytes at
314      * offset {@code 0} through {@code src.byteSize() - 1} in the source segment are copied into this segment
315      * at offset {@code 0} through {@code src.byteSize() - 1}.
316      * If the source segment overlaps with this segment, then the copying is performed as if the bytes at
317      * offset {@code 0} through {@code src.byteSize() - 1} in the source segment were first copied into a
318      * temporary segment with size {@code bytes}, and then the contents of the temporary segment were copied into
319      * this segment at offset {@code 0} through {@code src.byteSize() - 1}.
320      * <p>
321      * The result of a bulk copy is unspecified if, in the uncommon case, the source segment does not overlap with
322      * this segment, but it instead refers to an overlapping regions of the same backing storage using different addresses.
323      * For example, this may occur if the same file is {@link MemorySegment#mapFromPath mapped} to two segments.
324      *
325      * @param src the source segment.
326      * @throws IndexOutOfBoundsException if {src.byteSize() > this.byteSize()}.
327      * @throws IllegalStateException if either the source segment or this segment have been already closed,
328      * or if access occurs from a thread other than the thread owning either segment.
329      * @throws UnsupportedOperationException if either the source segment or this segment do not feature required access modes;
330      * more specifically, {@code src} should feature at least the {@link MemorySegment#READ} access mode,
331      * while this segment should feature at least the {@link MemorySegment#WRITE} access mode.
332      */
333     void copyFrom(MemorySegment src);
334 
335     /**
336      * Wraps this segment in a {@link ByteBuffer}. Some of the properties of the returned buffer are linked to
337      * the properties of this segment. For instance, if this segment is <em>immutable</em>
338      * (e.g. the segment has access mode {@link #READ} but not {@link #WRITE}), then the resulting buffer is <em>read-only</em>
339      * (see {@link ByteBuffer#isReadOnly()}. Additionally, if this is a native memory segment, the resulting buffer is
340      * <em>direct</em> (see {@link ByteBuffer#isDirect()}).
341      * <p>
342      * The life-cycle of the returned buffer will be tied to that of this segment. That means that if the this segment
343      * is closed (see {@link MemorySegment#close()}, accessing the returned
344      * buffer will throw an {@link IllegalStateException}.
345      * <p>
346      * The resulting buffer's byte order is {@link java.nio.ByteOrder#BIG_ENDIAN}; this can be changed using
347      * {@link ByteBuffer#order(java.nio.ByteOrder)}.
348      *
349      * @return a {@link ByteBuffer} view of this memory segment.
350      * @throws UnsupportedOperationException if this segment cannot be mapped onto a {@link ByteBuffer} instance,
351      * e.g. because it models an heap-based segment that is not based on a {@code byte[]}), or if its size is greater
352      * than {@link Integer#MAX_VALUE}, or if the segment does not support the {@link #READ} access mode.
353      */
354     ByteBuffer asByteBuffer();
355 
356     /**
357      * Copy the contents of this memory segment into a fresh byte array.
358      * @return a fresh byte array copy of this memory segment.
359      * @throws UnsupportedOperationException if this segment's contents cannot be copied into a {@link byte[]} instance,
360      * e.g. its size is greater than {@link Integer#MAX_VALUE}.
361      * @throws IllegalStateException if this segment has been closed, or if access occurs from a thread other than the
362      * thread owning this segment.
363      */
364     byte[] toByteArray();
365 
366     /**
367      * Creates a new buffer memory segment that models the memory associated with the given byte
368      * buffer. The segment starts relative to the buffer's position (inclusive)
369      * and ends relative to the buffer's limit (exclusive).
370      * <p>
371      * The resulting memory segment keeps a reference to the backing buffer, to ensure it remains <em>reachable</em>
372      * for the life-time of the segment.
373      *
374      * @param bb the byte buffer backing the buffer memory segment.
375      * @return a new buffer memory segment.
376      */
377     static MemorySegment ofByteBuffer(ByteBuffer bb) {
378         return AbstractMemorySegmentImpl.ofBuffer(bb);
379     }
380 
381     /**
382      * Creates a new array memory segment that models the memory associated with a given heap-allocated byte array.
383      * <p>
384      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
385      * for the life-time of the segment.
386      *
387      * @param arr the primitive array backing the array memory segment.
388      * @return a new array memory segment.
389      */
390     static MemorySegment ofArray(byte[] arr) {
391         return HeapMemorySegmentImpl.makeArraySegment(arr);
392     }
393 
394     /**
395      * Creates a new array memory segment that models the memory associated with a given heap-allocated char array.
396      * <p>
397      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
398      * for the life-time of the segment.
399      *
400      * @param arr the primitive array backing the array memory segment.
401      * @return a new array memory segment.
402      */
403     static MemorySegment ofArray(char[] arr) {
404         return HeapMemorySegmentImpl.makeArraySegment(arr);
405     }
406 
407     /**
408      * Creates a new array memory segment that models the memory associated with a given heap-allocated short array.
409      * <p>
410      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
411      * for the life-time of the segment.
412      *
413      * @param arr the primitive array backing the array memory segment.
414      * @return a new array memory segment.
415      */
416     static MemorySegment ofArray(short[] arr) {
417         return HeapMemorySegmentImpl.makeArraySegment(arr);
418     }
419 
420     /**
421      * Creates a new array memory segment that models the memory associated with a given heap-allocated int array.
422      * <p>
423      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
424      * for the life-time of the segment.
425      *
426      * @param arr the primitive array backing the array memory segment.
427      * @return a new array memory segment.
428      */
429     static MemorySegment ofArray(int[] arr) {
430         return HeapMemorySegmentImpl.makeArraySegment(arr);
431     }
432 
433     /**
434      * Creates a new array memory segment that models the memory associated with a given heap-allocated float array.
435      * <p>
436      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
437      * for the life-time of the segment.
438      *
439      * @param arr the primitive array backing the array memory segment.
440      * @return a new array memory segment.
441      */
442     static MemorySegment ofArray(float[] arr) {
443         return HeapMemorySegmentImpl.makeArraySegment(arr);
444     }
445 
446     /**
447      * Creates a new array memory segment that models the memory associated with a given heap-allocated long array.
448      * <p>
449      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
450      * for the life-time of the segment.
451      *
452      * @param arr the primitive array backing the array memory segment.
453      * @return a new array memory segment.
454      */
455     static MemorySegment ofArray(long[] arr) {
456         return HeapMemorySegmentImpl.makeArraySegment(arr);
457     }
458 
459     /**
460      * Creates a new array memory segment that models the memory associated with a given heap-allocated double array.
461      * <p>
462      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
463      * for the life-time of the segment.
464      *
465      * @param arr the primitive array backing the array memory segment.
466      * @return a new array memory segment.
467      */
468     static MemorySegment ofArray(double[] arr) {
469         return HeapMemorySegmentImpl.makeArraySegment(arr);
470     }
471 
472     /**
473      * Creates a new native memory segment that models a newly allocated block of off-heap memory with given layout.
474      * <p>
475      * This is equivalent to the following code:
476      * <blockquote><pre>{@code
477     allocateNative(layout.bytesSize(), layout.bytesAlignment());
478      * }</pre></blockquote>
479      *
480      * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
481      * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
482      * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
483      *
484      * @param layout the layout of the off-heap memory block backing the native memory segment.
485      * @return a new native memory segment.
486      * @throws IllegalArgumentException if the specified layout has illegal size or alignment constraint.
487      */
488     static MemorySegment allocateNative(MemoryLayout layout) {
489         return allocateNative(layout.byteSize(), layout.byteAlignment());
490     }
491 
492     /**
493      * Creates a new native memory segment that models a newly allocated block of off-heap memory with given size (in bytes).
494      * <p>
495      * This is equivalent to the following code:
496      * <blockquote><pre>{@code
497 allocateNative(bytesSize, 1);
498      * }</pre></blockquote>
499      *
500      * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
501      * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
502      * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
503      *
504      * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment.
505      * @return a new native memory segment.
506      * @throws IllegalArgumentException if {@code bytesSize < 0}.
507      */
508     static MemorySegment allocateNative(long bytesSize) {
509         return allocateNative(bytesSize, 1);
510     }
511 
512     /**
513      * Creates a new mapped memory segment that models a memory-mapped region of a file from a given path.
514      *
515      * @implNote When obtaining a mapped segment from a newly created file, the initialization state of the contents of the block
516      * of mapped memory associated with the returned mapped memory segment is unspecified and should not be relied upon.
517      *
518      * @param path the path to the file to memory map.
519      * @param bytesSize the size (in bytes) of the mapped memory backing the memory segment.
520      * @param mapMode a file mapping mode, see {@link FileChannel#map(FileChannel.MapMode, long, long)}; the chosen mapping mode
521      *                might affect the behavior of the returned memory mapped segment (see {@link MappedMemorySegment#force()}).
522      * @return a new mapped memory segment.
523      * @throws IllegalArgumentException if {@code bytesSize < 0}.
524      * @throws UnsupportedOperationException if an unsupported map mode is specified.
525      * @throws IOException if the specified path does not point to an existing file, or if some other I/O error occurs.
526      */
527     static MappedMemorySegment mapFromPath(Path path, long bytesSize, FileChannel.MapMode mapMode) throws IOException {
528         return MappedMemorySegmentImpl.makeMappedSegment(path, bytesSize, mapMode);
529     }
530 
531     /**
532      * Creates a new native memory segment that models a newly allocated block of off-heap memory with given size and
533      * alignment constraint (in bytes).
534      *
535      * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
536      * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
537      * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
538      *
539      * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment.
540      * @param alignmentBytes the alignment constraint (in bytes) of the off-heap memory block backing the native memory segment.
541      * @return a new native memory segment.
542      * @throws IllegalArgumentException if {@code bytesSize < 0}, {@code alignmentBytes < 0}, or if {@code alignmentBytes}
543      * is not a power of 2.
544      */
545     static MemorySegment allocateNative(long bytesSize, long alignmentBytes) {
546         if (bytesSize <= 0) {
547             throw new IllegalArgumentException("Invalid allocation size : " + bytesSize);
548         }
549 
550         if (alignmentBytes < 0 ||
551                 ((alignmentBytes & (alignmentBytes - 1)) != 0L)) {
552             throw new IllegalArgumentException("Invalid alignment constraint : " + alignmentBytes);
553         }
554 
555         return NativeMemorySegmentImpl.makeNativeSegment(bytesSize, alignmentBytes);
556     }
557 
558     /**
559      * Returns a new native memory segment with given base address and size; the returned segment has its own temporal
560      * bounds, and can therefore be closed; closing such a segment can optionally result in calling an user-provided cleanup
561      * action. This method can be very useful when interacting with custom native memory sources (e.g. custom allocators,
562      * GPU memory, etc.), where an address to some underlying memory region is typically obtained from native code
563      * (often as a plain {@code long} value).
564      * <p>
565      * This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
566      * the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
567      * restricted methods, and use safe and supported functionalities, where possible.
568      *
569      * @param addr the desired base address
570      * @param bytesSize the desired size.
571      * @param owner the desired owner thread. If {@code owner == null}, the returned segment is <em>not</em> confined.
572      * @param cleanup a cleanup action to be executed when the {@link MemorySegment#close()} method is called on the
573      *                returned segment. If {@code cleanup == null}, no cleanup action is executed.
574      * @param attachment an object that must be kept alive by the returned segment; this can be useful when
575      *                   the returned segment depends on memory which could be released if a certain object
576      *                   is determined to be unreacheable. In most cases this will be set to {@code null}.
577      * @return a new native memory segment with given base address, size, owner, cleanup action and object attachment.
578      * @throws IllegalArgumentException if {@code bytesSize <= 0}.
579      * @throws UnsupportedOperationException if {@code addr} is associated with an heap segment.
580      * @throws IllegalAccessError if the runtime property {@code foreign.restricted} is not set to either
581      * {@code permit}, {@code warn} or {@code debug} (the default value is set to {@code deny}).
582      * @throws NullPointerException if {@code addr == null}.
583      */
584     static MemorySegment ofNativeRestricted(MemoryAddress addr, long bytesSize, Thread owner, Runnable cleanup, Object attachment) {
585         Objects.requireNonNull(addr);
586         if (bytesSize <= 0) {
587             throw new IllegalArgumentException("Invalid size : " + bytesSize);
588         }
589         Utils.checkRestrictedAccess("MemorySegment.ofNativeRestricted");
590         return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, bytesSize, owner, cleanup, attachment);
591     }
592 
593     // access mode masks
594 
595     /**
596      * Read access mode; read operations are supported by a segment which supports this access mode.
597      * @see MemorySegment#accessModes()
598      * @see MemorySegment#withAccessModes(int)
599      */
600     int READ = 1;
601 
602     /**
603      * Write access mode; write operations are supported by a segment which supports this access mode.
604      * @see MemorySegment#accessModes()
605      * @see MemorySegment#withAccessModes(int)
606      */
607     int WRITE = READ << 1;
608 
609     /**
610      * Close access mode; calling {@link #close()} is supported by a segment which supports this access mode.
611      * @see MemorySegment#accessModes()
612      * @see MemorySegment#withAccessModes(int)
613      */
614     int CLOSE = WRITE << 1;
615 
616     /**
617      * Acquire access mode; this segment support sharing with threads other than the owner thread, via spliterator
618      * (see {@link #spliterator(MemorySegment, SequenceLayout)}).
619      * @see MemorySegment#accessModes()
620      * @see MemorySegment#withAccessModes(int)
621      */
622     int ACQUIRE = CLOSE << 1;
623 
624     /**
625      * Handoff access mode; this segment support serial thread-confinement via thread ownership changes
626      * (see {@link #withOwnerThread(Thread)}).
627      * @see MemorySegment#accessModes()
628      * @see MemorySegment#withAccessModes(int)
629      */
630     int HANDOFF = ACQUIRE << 1;
631 }