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.NativeMemorySegmentImpl;
  35 import jdk.internal.foreign.Utils;
  36 
  37 import java.io.IOException;
  38 import java.nio.channels.FileChannel;
  39 import java.nio.file.Path;
  40 import java.util.Objects;
  41 import java.util.Spliterator;
  42 import java.util.function.Consumer;
  43 
  44 /**
  45  * A memory segment models a contiguous region of memory. A memory segment is associated with both spatial
  46  * and temporal bounds. Spatial bounds ensure that memory access operations on a memory segment cannot affect a memory location
  47  * which falls <em>outside</em> the boundaries of the memory segment being accessed. Temporal checks ensure that memory access
  48  * operations on a segment cannot occur after a memory segment has been closed (see {@link MemorySegment#close()}).
  49  * <p>
  50  * All implementations of this interface must be <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>;
  51  * use of identity-sensitive operations (including reference equality ({@code ==}), identity hash code, or synchronization) on
  52  * instances of {@code MemorySegment} may have unpredictable results and should be avoided. The {@code equals} method should
  53  * be used for comparisons.
  54  * <p>
  55  * Non-platform classes should not implement {@linkplain MemorySegment} directly.
  56  *
  57  * <h2>Constructing memory segments from different sources</h2>
  58  *
  59  * There are multiple ways to obtain a memory segment. First, memory segments backed by off-heap memory can
  60  * be allocated using one of the many factory methods provided (see {@link MemorySegment#allocateNative(MemoryLayout)},
  61  * {@link MemorySegment#allocateNative(long)} and {@link MemorySegment#allocateNative(long, long)}). Memory segments obtained
  62  * in this way are called <em>native memory segments</em>.
  63  * <p>
  64  * It is also possible to obtain a memory segment backed by an existing heap-allocated Java array,
  65  * using one of the provided factory methods (e.g. {@link MemorySegment#ofArray(int[])}). Memory segments obtained
  66  * in this way are called <em>array memory segments</em>.
  67  * <p>
  68  * It is possible to obtain a memory segment backed by an existing Java byte buffer (see {@link ByteBuffer}),
  69  * using the factory method {@link MemorySegment#ofByteBuffer(ByteBuffer)}.
  70  * Memory segments obtained in this way are called <em>buffer memory segments</em>. Note that buffer memory segments might
  71  * be backed by native memory (as in the case of native memory segments) or heap memory (as in the case of array memory segments),
  72  * depending on the characteristics of the byte buffer instance the segment is associated with. For instance, a buffer memory
  73  * segment obtained from a byte buffer created with the {@link ByteBuffer#allocateDirect(int)} method will be backed
  74  * by native memory.
  75  * <p>
  76  * Finally, it is also possible to obtain a memory segment backed by a memory-mapped file using the factory method
  77  * {@link MemorySegment#mapFromPath(Path, long, FileChannel.MapMode)}. Such memory segments are called <em>mapped memory segments</em>
  78  * (see {@link MappedMemorySegment}).
  79  *
  80  * <h2>Closing a memory segment</h2>
  81  *
  82  * Memory segments are closed explicitly (see {@link MemorySegment#close()}). In general when a segment is closed, all off-heap
  83  * resources associated with it are released; this has different meanings depending on the kind of memory segment being
  84  * considered:
  85  * <ul>
  86  *     <li>closing a native memory segment results in <em>freeing</em> the native memory associated with it</li>
  87  *     <li>closing a mapped memory segment results in the backing memory-mapped file to be unmapped</li>
  88  *     <li>closing a buffer, or a heap segment does not have any side-effect, other than marking the segment
  89  *     as <em>not alive</em> (see {@link MemorySegment#isAlive()}). Also, since the buffer and heap segments might keep
  90  *     strong references to the original buffer or array instance, it is the responsibility of clients to ensure that
  91  *     these segments are discarded in a timely manner, so as not to prevent garbage collection to reclaim the underlying
  92  *     objects.</li>
  93  * </ul>
  94  *
  95  * <h2><a id = "thread-confinement">Thread confinement</a></h2>
  96  *
  97  * Memory segments support strong thread-confinement guarantees. Upon creation, they are assigned an <em>owner thread</em>,
  98  * typically the thread which initiated the creation operation. After creation, only the owner thread will be allowed
  99  * to directly manipulate the memory segment (e.g. close the memory segment) or access the underlying memory associated with
 100  * the segment using a memory access var handle. Any attempt to perform such operations from a thread other than the
 101  * owner thread will result in a runtime failure.
 102  * <p>
 103  * Memory segments support <em>serial thread confinement</em>; that is, ownership of a memory segment can change (see
 104  * {@link #withOwnerThread(Thread)}). This allows, for instance, for two threads {@code A} and {@code B} to share
 105  * a segment in a controlled, cooperative and race-free fashion.
 106  * <p>
 107  * In some cases, it might be useful for multiple threads to process the contents of the same memory segment concurrently
 108  * (e.g. in the case of parallel processing); while memory segments provide strong confinement guarantees, it is possible
 109  * to obtain a {@link Spliterator} from a segment, which can be used to slice the segment and allow multiple thread to
 110  * work in parallel on disjoint segment slices (this assumes that the access mode {@link #ACQUIRE} is set).
 111  * For instance, the following code can be used to sum all int values in a memory segment in parallel:
 112  * <blockquote><pre>{@code
 113 MemorySegment segment = ...
 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(MemorySegment.spliterator(segment, SEQUENCE_LAYOUT), true)
 117             .mapToInt(s -> (int)VH_int.get(s.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}, {@link #ACQUIRE} and {@link #HANDOFF}. 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 segment 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}. The spliterator returns segments that feature the same
 181      * <a href="#access-modes">access modes</a> as the given segment less the {@link #CLOSE} access mode.
 182      * <p>
 183      * The returned spliterator effectively allows to slice a segment into disjoint sub-segments, which can then
 184      * be processed in parallel by multiple threads (if the access mode {@link #ACQUIRE} is set).
 185      * While closing the segment (see {@link #close()}) during pending concurrent execution will generally
 186      * fail with an exception, it is possible to close a segment when a spliterator has been obtained but no thread
 187      * is actively working on it using {@link Spliterator#tryAdvance(Consumer)}; in such cases, any subsequent call
 188      * to {@link Spliterator#tryAdvance(Consumer)} will fail with an exception.
 189      * @param segment the segment to be used for splitting.
 190      * @param layout the layout to be used for splitting.
 191      * @param <S> the memory segment type
 192      * @return the element spliterator for this segment
 193      * @throws IllegalStateException if the segment is not <em>alive</em>, or if access occurs from a thread other than the
 194      * thread owning this segment
 195      */
 196     static <S extends MemorySegment> Spliterator<S> spliterator(S segment, SequenceLayout layout) {
 197         return AbstractMemorySegmentImpl.spliterator(segment, layout);
 198     }
 199 
 200     /**
 201      * The thread owning this segment.
 202      * @return the thread owning this segment.
 203      */
 204     Thread ownerThread();
 205 
 206     /**
 207      * Obtains a new memory segment backed by the same underlying memory region as this segment,
 208      * but with different owner thread. As a side-effect, this segment will be marked as <em>not alive</em>,
 209      * and subsequent operations on this segment will result in runtime errors.
 210      * <p>
 211      * Write accesses to the segment's content <a href="../../../java/util/concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
 212      * 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
 213      * the new owner thread.
 214      *
 215      * @param newOwner the new owner thread.
 216      * @return a new memory segment backed by the same underlying memory region as this segment,
 217      *      owned by {@code newOwner}.
 218      * @throws IllegalStateException if this segment is not <em>alive</em>, or if access occurs from a thread other than the
 219      * thread owning this segment, or if the segment cannot be closed because it is being operated upon by a different
 220      * thread (see {@link #spliterator(MemorySegment, SequenceLayout)}).
 221      * @throws NullPointerException if {@code newOwner == null}
 222      * @throws IllegalArgumentException if the segment is already a confined segment owner by {@code newOnwer}.
 223      * @throws UnsupportedOperationException if this segment does not support the {@link #HANDOFF} access mode.
 224      */
 225     MemorySegment withOwnerThread(Thread newOwner);
 226 
 227     /**
 228      * The size (in bytes) of this memory segment.
 229      * @return The size (in bytes) of this memory segment.
 230      */
 231     long byteSize();
 232 
 233     /**
 234      * Obtains a segment view with specific <a href="#access-modes">access modes</a>. Supported access modes are {@link #READ}, {@link #WRITE},
 235      * {@link #CLOSE}, {@link #ACQUIRE} and {@link #HANDOFF}. It is generally not possible to go from a segment with stricter access modes
 236      * to one with less strict access modes. For instance, attempting to add {@link #WRITE} access mode to a read-only segment
 237      * will be met with an exception.
 238      * @param accessModes an ORed mask of zero or more access modes.
 239      * @return a segment view with specific access modes.
 240      * @throws UnsupportedOperationException when {@code mask} is an access mask which is less strict than the one supported by this
 241      * segment.
 242      */
 243     MemorySegment withAccessModes(int accessModes);
 244 
 245     /**
 246      * Does this segment support a given set of access modes?
 247      * @param accessModes an ORed mask of zero or more access modes.
 248      * @return true, if the access modes in {@code accessModes} are stricter than the ones supported by this segment.
 249      */
 250     boolean hasAccessModes(int accessModes);
 251 
 252     /**
 253      * Returns the <a href="#access-modes">access modes</a> associated with this segment; the result is represented as ORed values from
 254      * {@link #READ}, {@link #WRITE}, {@link #CLOSE}, {@link #ACQUIRE} and {@link #HANDOFF}.
 255      * @return the access modes associated with this segment.
 256      */
 257     int accessModes();
 258 
 259     /**
 260      * Obtains a new memory segment view whose base address is the same as the base address of this segment plus a given offset,
 261      * and whose new size is specified by the given argument.
 262      * @param offset The new segment base offset (relative to the current segment base address), specified in bytes.
 263      * @param newSize The new segment size, specified in bytes.
 264      * @return a new memory segment view with updated base/limit addresses.
 265      * @throws IndexOutOfBoundsException if {@code offset < 0}, {@code offset > byteSize()}, {@code newSize < 0}, or {@code newSize > byteSize() - offset}
 266      */
 267     MemorySegment asSlice(long offset, long newSize);
 268 
 269     /**
 270      * Is this segment alive?
 271      * @return true, if the segment is alive.
 272      * @see MemorySegment#close()
 273      */
 274     boolean isAlive();
 275 
 276     /**
 277      * Closes this memory segment. Once a memory segment has been closed, any attempt to use the memory segment,
 278      * or to access the memory associated with the segment will fail with {@link IllegalStateException}. Depending on
 279      * the kind of memory segment being closed, calling this method further trigger deallocation of all the resources
 280      * associated with the memory segment.
 281      * @throws IllegalStateException if this segment is not <em>alive</em>, or if access occurs from a thread other than the
 282      * thread owning this segment, or if the segment cannot be closed because it is being operated upon by a different
 283      * thread (see {@link #spliterator(MemorySegment, SequenceLayout)}).
 284      * @throws UnsupportedOperationException if this segment does not support the {@link #CLOSE} access mode.
 285      */
 286     void close();
 287 
 288     /**
 289      * Wraps this segment in a {@link ByteBuffer}. Some of the properties of the returned buffer are linked to
 290      * the properties of this segment. For instance, if this segment is <em>immutable</em>
 291      * (e.g. the segment has access mode {@link #READ} but not {@link #WRITE}), then the resulting buffer is <em>read-only</em>
 292      * (see {@link ByteBuffer#isReadOnly()}. Additionally, if this is a native memory segment, the resulting buffer is
 293      * <em>direct</em> (see {@link ByteBuffer#isDirect()}).
 294      * <p>
 295      * The life-cycle of the returned buffer will be tied to that of this segment. That means that if the this segment
 296      * is closed (see {@link MemorySegment#close()}, accessing the returned
 297      * buffer will throw an {@link IllegalStateException}.
 298      * <p>
 299      * The resulting buffer's byte order is {@link java.nio.ByteOrder#BIG_ENDIAN}; this can be changed using
 300      * {@link ByteBuffer#order(java.nio.ByteOrder)}.
 301      *
 302      * @return a {@link ByteBuffer} view of this memory segment.
 303      * @throws UnsupportedOperationException if this segment cannot be mapped onto a {@link ByteBuffer} instance,
 304      * e.g. because it models an heap-based segment that is not based on a {@code byte[]}), or if its size is greater
 305      * than {@link Integer#MAX_VALUE}, or if the segment does not support the {@link #READ} access mode.
 306      */
 307     ByteBuffer asByteBuffer();
 308 
 309     /**
 310      * Copy the contents of this memory segment into a fresh byte array.
 311      * @return a fresh byte array copy of this memory segment.
 312      * @throws UnsupportedOperationException if this segment's contents cannot be copied into a {@link byte[]} instance,
 313      * e.g. its size is greater than {@link Integer#MAX_VALUE}.
 314      * @throws IllegalStateException if this segment has been closed, or if access occurs from a thread other than the
 315      * thread owning this segment.
 316      */
 317     byte[] toByteArray();
 318 
 319     /**
 320      * Creates a new buffer memory segment that models the memory associated with the given byte
 321      * buffer. The segment starts relative to the buffer's position (inclusive)
 322      * and ends relative to the buffer's limit (exclusive).
 323      * <p>
 324      * The segment will feature all <a href="#access-modes">access modes</a>, unless the given
 325      * buffer is {@linkplain ByteBuffer#isReadOnly() read-only} in which case the segment will
 326      * not feature the {@link #WRITE} access mode.
 327      * <p>
 328      * The resulting memory segment keeps a reference to the backing buffer, to ensure it remains <em>reachable</em>
 329      * for the life-time of the segment.
 330      *
 331      * @param bb the byte buffer backing the buffer memory segment.
 332      * @return a new buffer memory segment.
 333      */
 334     static MemorySegment ofByteBuffer(ByteBuffer bb) {
 335         return AbstractMemorySegmentImpl.ofBuffer(bb);
 336     }
 337 
 338     /**
 339      * Creates a new array memory segment that models the memory associated with a given heap-allocated byte array.
 340      * <p>
 341      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
 342      * for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
 343      *
 344      * @param arr the primitive array backing the array memory segment.
 345      * @return a new array memory segment.
 346      */
 347     static MemorySegment ofArray(byte[] arr) {
 348         return HeapMemorySegmentImpl.makeArraySegment(arr);
 349     }
 350 
 351     /**
 352      * Creates a new array memory segment that models the memory associated with a given heap-allocated char array.
 353      * <p>
 354      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
 355      * for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
 356      *
 357      * @param arr the primitive array backing the array memory segment.
 358      * @return a new array memory segment.
 359      */
 360     static MemorySegment ofArray(char[] arr) {
 361         return HeapMemorySegmentImpl.makeArraySegment(arr);
 362     }
 363 
 364     /**
 365      * Creates a new array memory segment that models the memory associated with a given heap-allocated short array.
 366      * <p>
 367      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
 368      * for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
 369      *
 370      * @param arr the primitive array backing the array memory segment.
 371      * @return a new array memory segment.
 372      */
 373     static MemorySegment ofArray(short[] arr) {
 374         return HeapMemorySegmentImpl.makeArraySegment(arr);
 375     }
 376 
 377     /**
 378      * Creates a new array memory segment that models the memory associated with a given heap-allocated int array.
 379      * <p>
 380      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
 381      * for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
 382      *
 383      * @param arr the primitive array backing the array memory segment.
 384      * @return a new array memory segment.
 385      */
 386     static MemorySegment ofArray(int[] arr) {
 387         return HeapMemorySegmentImpl.makeArraySegment(arr);
 388     }
 389 
 390     /**
 391      * Creates a new array memory segment that models the memory associated with a given heap-allocated float array.
 392      * <p>
 393      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
 394      * for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
 395      *
 396      * @param arr the primitive array backing the array memory segment.
 397      * @return a new array memory segment.
 398      */
 399     static MemorySegment ofArray(float[] arr) {
 400         return HeapMemorySegmentImpl.makeArraySegment(arr);
 401     }
 402 
 403     /**
 404      * Creates a new array memory segment that models the memory associated with a given heap-allocated long array.
 405      * <p>
 406      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
 407      * for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
 408      *
 409      * @param arr the primitive array backing the array memory segment.
 410      * @return a new array memory segment.
 411      */
 412     static MemorySegment ofArray(long[] arr) {
 413         return HeapMemorySegmentImpl.makeArraySegment(arr);
 414     }
 415 
 416     /**
 417      * Creates a new array memory segment that models the memory associated with a given heap-allocated double array.
 418      * <p>
 419      * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
 420      * for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
 421      *
 422      * @param arr the primitive array backing the array memory segment.
 423      * @return a new array memory segment.
 424      */
 425     static MemorySegment ofArray(double[] arr) {
 426         return HeapMemorySegmentImpl.makeArraySegment(arr);
 427     }
 428 
 429     /**
 430      * Creates a new native memory segment that models a newly allocated block of off-heap memory with given layout.
 431      * <p>
 432      * This is equivalent to the following code:
 433      * <blockquote><pre>{@code
 434     allocateNative(layout.bytesSize(), layout.bytesAlignment());
 435      * }</pre></blockquote>
 436      *
 437      * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
 438      * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
 439      * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
 440      *
 441      * @param layout the layout of the off-heap memory block backing the native memory segment.
 442      * @return a new native memory segment.
 443      * @throws IllegalArgumentException if the specified layout has illegal size or alignment constraint.
 444      */
 445     static MemorySegment allocateNative(MemoryLayout layout) {
 446         return allocateNative(layout.byteSize(), layout.byteAlignment());
 447     }
 448 
 449     /**
 450      * Creates a new native memory segment that models a newly allocated block of off-heap memory with given size (in bytes).
 451      * <p>
 452      * This is equivalent to the following code:
 453      * <blockquote><pre>{@code
 454 allocateNative(bytesSize, 1);
 455      * }</pre></blockquote>
 456      *
 457      * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
 458      * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
 459      * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
 460      *
 461      * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment.
 462      * @return a new native memory segment.
 463      * @throws IllegalArgumentException if {@code bytesSize < 0}.
 464      */
 465     static MemorySegment allocateNative(long bytesSize) {
 466         return allocateNative(bytesSize, 1);
 467     }
 468 
 469     /**
 470      * Creates a new mapped memory segment that models a memory-mapped region of a file from a given path.
 471      * <p>
 472      * The segment will feature all <a href="#access-modes">access modes</a>, unless the given mapping mode
 473      * is {@linkplain FileChannel.MapMode#READ_ONLY READ_ONLY}, in which case the segment will not feature
 474      * the {@link #WRITE} access mode.
 475      *
 476      * @implNote When obtaining a mapped segment from a newly created file, the initialization state of the contents of the block
 477      * of mapped memory associated with the returned mapped memory segment is unspecified and should not be relied upon.
 478      *
 479      * @param path the path to the file to memory map.
 480      * @param bytesSize the size (in bytes) of the mapped memory backing the memory segment.
 481      * @param mapMode a file mapping mode, see {@link FileChannel#map(FileChannel.MapMode, long, long)}; the chosen mapping mode
 482      *                might affect the behavior of the returned memory mapped segment (see {@link MappedMemorySegment#force()}).
 483      * @return a new mapped memory segment.
 484      * @throws IllegalArgumentException if {@code bytesSize < 0}.
 485      * @throws UnsupportedOperationException if an unsupported map mode is specified.
 486      * @throws IOException if the specified path does not point to an existing file, or if some other I/O error occurs.
 487      */
 488     static MappedMemorySegment mapFromPath(Path path, long bytesSize, FileChannel.MapMode mapMode) throws IOException {
 489         return MappedMemorySegmentImpl.makeMappedSegment(path, bytesSize, mapMode);
 490     }
 491 
 492     /**
 493      * Creates a new native memory segment that models a newly allocated block of off-heap memory with given size and
 494      * alignment constraint (in bytes). The segment will feature all <a href="#access-modes">access modes</a>.
 495      *
 496      * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
 497      * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
 498      * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
 499      *
 500      * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment.
 501      * @param alignmentBytes the alignment constraint (in bytes) of the off-heap memory block backing the native memory segment.
 502      * @return a new native memory segment.
 503      * @throws IllegalArgumentException if {@code bytesSize < 0}, {@code alignmentBytes < 0}, or if {@code alignmentBytes}
 504      * is not a power of 2.
 505      */
 506     static MemorySegment allocateNative(long bytesSize, long alignmentBytes) {
 507         if (bytesSize <= 0) {
 508             throw new IllegalArgumentException("Invalid allocation size : " + bytesSize);
 509         }
 510 
 511         if (alignmentBytes < 0 ||
 512                 ((alignmentBytes & (alignmentBytes - 1)) != 0L)) {
 513             throw new IllegalArgumentException("Invalid alignment constraint : " + alignmentBytes);
 514         }
 515 
 516         return NativeMemorySegmentImpl.makeNativeSegment(bytesSize, alignmentBytes);
 517     }
 518 
 519     /**
 520      * Returns a new native memory segment with given base address and size; the returned segment has its own temporal
 521      * bounds, and can therefore be closed; closing such a segment can optionally result in calling an user-provided cleanup
 522      * action. This method can be very useful when interacting with custom native memory sources (e.g. custom allocators,
 523      * GPU memory, etc.), where an address to some underlying memory region is typically obtained from native code
 524      * (often as a plain {@code long} value). The segment will feature all <a href="#access-modes">access modes</a>.
 525      * <p>
 526      * This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
 527      * the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
 528      * restricted methods, and use safe and supported functionalities, where possible.
 529      *
 530      * @param addr the desired base address
 531      * @param bytesSize the desired size.
 532      * @param owner the desired owner thread. If {@code owner == null}, the returned segment is <em>not</em> confined.
 533      * @param cleanup a cleanup action to be executed when the {@link MemorySegment#close()} method is called on the
 534      *                returned segment. If {@code cleanup == null}, no cleanup action is executed.
 535      * @param attachment an object that must be kept alive by the returned segment; this can be useful when
 536      *                   the returned segment depends on memory which could be released if a certain object
 537      *                   is determined to be unreacheable. In most cases this will be set to {@code null}.
 538      * @return a new native memory segment with given base address, size, owner, cleanup action and object attachment.
 539      * @throws IllegalArgumentException if {@code bytesSize <= 0}.
 540      * @throws UnsupportedOperationException if {@code addr} is associated with an heap segment.
 541      * @throws IllegalAccessError if the runtime property {@code foreign.restricted} is not set to either
 542      * {@code permit}, {@code warn} or {@code debug} (the default value is set to {@code deny}).
 543      * @throws NullPointerException if {@code addr == null}.
 544      */
 545     static MemorySegment ofNativeRestricted(MemoryAddress addr, long bytesSize, Thread owner, Runnable cleanup, Object attachment) {
 546         Objects.requireNonNull(addr);
 547         if (bytesSize <= 0) {
 548             throw new IllegalArgumentException("Invalid size : " + bytesSize);
 549         }
 550         Utils.checkRestrictedAccess("MemorySegment.ofNativeRestricted");
 551         return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, bytesSize, owner, cleanup, attachment);
 552     }
 553 
 554     // access mode masks
 555 
 556     /**
 557      * Read access mode; read operations are supported by a segment which supports this access mode.
 558      * @see MemorySegment#accessModes()
 559      * @see MemorySegment#withAccessModes(int)
 560      */
 561     int READ = 1;
 562 
 563     /**
 564      * Write access mode; write operations are supported by a segment which supports this access mode.
 565      * @see MemorySegment#accessModes()
 566      * @see MemorySegment#withAccessModes(int)
 567      */
 568     int WRITE = READ << 1;
 569 
 570     /**
 571      * Close access mode; calling {@link #close()} is supported by a segment which supports this access mode.
 572      * @see MemorySegment#accessModes()
 573      * @see MemorySegment#withAccessModes(int)
 574      */
 575     int CLOSE = WRITE << 1;
 576 
 577     /**
 578      * Acquire access mode; this segment support sharing with threads other than the owner thread, via spliterator
 579      * (see {@link #spliterator(MemorySegment, SequenceLayout)}).
 580      * @see MemorySegment#accessModes()
 581      * @see MemorySegment#withAccessModes(int)
 582      */
 583     int ACQUIRE = CLOSE << 1;
 584 
 585     /**
 586      * Handoff access mode; this segment support serial thread-confinement via thread ownership changes
 587      * (see {@link #withOwnerThread(Thread)}).
 588      * @see MemorySegment#accessModes()
 589      * @see MemorySegment#withAccessModes(int)
 590      */
 591     int HANDOFF = ACQUIRE << 1;
 592 }