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.io.UncheckedIOException;
 30 import java.nio.ByteBuffer;
 31 
 32 import jdk.internal.foreign.AbstractMemorySegmentImpl;
 33 import jdk.internal.foreign.HeapMemorySegmentImpl;
 34 import jdk.internal.foreign.MappedMemorySegmentImpl;
 35 import jdk.internal.foreign.ResourceScopeImpl;
 36 import jdk.internal.foreign.NativeMemorySegmentImpl;
 37 import jdk.internal.reflect.CallerSensitive;
 38 import jdk.internal.reflect.Reflection;
 39 
 40 import java.io.IOException;
 41 import java.nio.channels.FileChannel;
 42 import java.nio.file.Path;
 43 import java.util.Objects;
 44 import java.util.Spliterator;
 45 import java.util.stream.Stream;
 46 
 47 /**
 48  * A memory segment models a contiguous region of memory. A memory segment is associated with both spatial
 49  * and temporal bounds (e.g. a {@link ResourceScope}). Spatial bounds ensure that memory access operations on a memory segment cannot affect a memory location
 50  * which falls <em>outside</em> the boundaries of the memory segment being accessed. Temporal bounds ensure that memory access
 51  * operations on a segment cannot occur after the resource scope associated with a memory segment has been closed (see {@link ResourceScope#close()}).
 52  * <p>
 53  * All implementations of this interface must be <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>;
 54  * programmers should treat instances that are {@linkplain Object#equals(Object) equal} as interchangeable and should not
 55  * use instances for synchronization, or unpredictable behavior may occur. For example, in a future release,
 56  * synchronization may fail. The {@code equals} method should be used for comparisons.
 57  * <p>
 58  * Non-platform classes should not implement {@linkplain MemorySegment} directly.
 59  *
 60  * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
 61  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
 62  *
 63  * <h2>Constructing memory segments</h2>
 64  *
 65  * There are multiple ways to obtain a memory segment. First, memory segments backed by off-heap memory can
 66  * be allocated using one of the many factory methods provided (see {@link MemorySegment#allocateNative(MemoryLayout, ResourceScope)},
 67  * {@link MemorySegment#allocateNative(long, ResourceScope)} and {@link MemorySegment#allocateNative(long, long, ResourceScope)}). Memory segments obtained
 68  * in this way are called <em>native memory segments</em>.
 69  * <p>
 70  * It is also possible to obtain a memory segment backed by an existing heap-allocated Java array,
 71  * using one of the provided factory methods (e.g. {@link MemorySegment#ofArray(int[])}). Memory segments obtained
 72  * in this way are called <em>array memory segments</em>.
 73  * <p>
 74  * It is possible to obtain a memory segment backed by an existing Java byte buffer (see {@link ByteBuffer}),
 75  * using the factory method {@link MemorySegment#ofByteBuffer(ByteBuffer)}.
 76  * Memory segments obtained in this way are called <em>buffer memory segments</em>. Note that buffer memory segments might
 77  * be backed by native memory (as in the case of native memory segments) or heap memory (as in the case of array memory segments),
 78  * depending on the characteristics of the byte buffer instance the segment is associated with. For instance, a buffer memory
 79  * segment obtained from a byte buffer created with the {@link ByteBuffer#allocateDirect(int)} method will be backed
 80  * by native memory.
 81  *
 82  * <h2>Mapping memory segments from files</h2>
 83  *
 84  * It is also possible to obtain a native memory segment backed by a memory-mapped file using the factory method
 85  * {@link MemorySegment#mapFile(Path, long, long, FileChannel.MapMode, ResourceScope)}. Such native memory segments are
 86  * called <em>mapped memory segments</em>; mapped memory segments are associated with an underlying file descriptor.
 87  * <p>
 88  * Contents of mapped memory segments can be {@linkplain #force() persisted} and {@linkplain #load() loaded} to and from the underlying file;
 89  * these capabilities are suitable replacements for some of the functionality in the {@link java.nio.MappedByteBuffer} class.
 90  * Note that, while it is possible to map a segment into a byte buffer (see {@link MemorySegment#asByteBuffer()}),
 91  * and then call e.g. {@link java.nio.MappedByteBuffer#force()} that way, this can only be done when the source segment
 92  * is small enough, due to the size limitation inherent to the ByteBuffer API.
 93  * <p>
 94  * Clients requiring sophisticated, low-level control over mapped memory segments, should consider writing
 95  * custom mapped memory segment factories; using {@link CLinker}, e.g. on Linux, it is possible to call {@code mmap}
 96  * with the desired parameters; the returned address can be easily wrapped into a memory segment, using
 97  * {@link MemoryAddress#ofLong(long)} and {@link MemoryAddress#asSegment(long, Runnable, ResourceScope)}.
 98  *
 99  * <h2>Lifecycle and confinement</h2>
100  *
101  * Memory segments are associated with a resource scope (see {@link ResourceScope}), which can be accessed using
102  * the {@link #scope()} method. As for all resources associated with a resource scope, a segment cannot be
103  * accessed after its corresponding scope has been closed. For instance, the following code will result in an
104  * exception:
105  * <blockquote><pre>{@code
106 MemorySegment segment = null;
107 try (ResourceScope scope = ResourceScope.newConfinedScope()) {
108     segment = MemorySegment.allocateNative(8, 1, scope);
109 }
110 MemoryAccess.getLong(segment); // already closed!
111  * }</pre></blockquote>
112  * Additionally, access to a memory segment is subject to the thread-confinement checks enforced by the owning scope; that is,
113  * if the segment is associated with a shared scope, it can be accessed by multiple threads; if it is associated with a confined
114  * scope, it can only be accessed by the thread which owns the scope.
115  * <p>
116  * Heap and buffer segments are always associated with a <em>global</em>, shared scope. This scope cannot be closed,
117  * and can be considered as <em>always alive</em>.
118  *
119  * <h2>Memory segment views</h2>
120  *
121  * Memory segments support <em>views</em>. For instance, it is possible to create an <em>immutable</em> view of a memory segment, as follows:
122  * <blockquote><pre>{@code
123 MemorySegment segment = ...
124 MemorySegment roSegment = segment.asReadOnly();
125  * }</pre></blockquote>
126  * It is also possible to create views whose spatial bounds are stricter than the ones of the original segment
127  * (see {@link MemorySegment#asSlice(long, long)}).
128  * <p>
129  * Temporal bounds of the original segment are inherited by the views; that is, when the scope associated with a segment
130  * is closed, all the views associated with that segment will also be rendered inaccessible.
131  * <p>
132  * To allow for interoperability with existing code, a byte buffer view can be obtained from a memory segment
133  * (see {@link #asByteBuffer()}). This can be useful, for instance, for those clients that want to keep using the
134  * {@link ByteBuffer} API, but need to operate on large memory segments. Byte buffers obtained in such a way support
135  * the same spatial and temporal access restrictions associated with the memory segment from which they originated.
136  *
137  * <h2>Stream support</h2>
138  *
139  * A client might obtain a {@link Stream} from a segment, which can then be used to slice the segment (according to a given
140  * element layout) and even allow multiple threads to work in parallel on disjoint segment slices
141  * (to do this, the segment has to be associated with a shared scope). The following code can be used to sum all int
142  * values in a memory segment in parallel:
143  *
144  * <blockquote><pre>{@code
145 try (ResourceScope scope = ResourceScope.newSharedScope()) {
146     SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_INT);
147     MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
148     VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
149     int sum = segment.elements(MemoryLayouts.JAVA_INT).parallel()
150                            .mapToInt(s -> (int)VH_int.get(s.address()))
151                            .sum();
152 }
153  * }</pre></blockquote>
154  *
155  * @implSpec
156  * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
157  */
158 public sealed interface MemorySegment extends Addressable permits AbstractMemorySegmentImpl {
159 
160     /**
161      * The base memory address associated with this memory segment.
162      * The returned memory address is associated with same resource scope as that associated with this segment.
163      * @return The base memory address.
164      */
165     @Override
166     MemoryAddress address();
167 
168     /**
169      * Returns a spliterator for this memory segment. The returned spliterator reports {@link Spliterator#SIZED},
170      * {@link Spliterator#SUBSIZED}, {@link Spliterator#IMMUTABLE}, {@link Spliterator#NONNULL} and {@link Spliterator#ORDERED}
171      * characteristics.
172      * <p>
173      * The returned spliterator splits this segment according to the specified element layout; that is,
174      * if the supplied layout has size N, then calling {@link Spliterator#trySplit()} will result in a spliterator serving
175      * approximately {@code S/N/2} elements (depending on whether N is even or not), where {@code S} is the size of
176      * this segment. As such, splitting is possible as long as {@code S/N >= 2}. The spliterator returns segments that feature the same
177      * scope as this given segment.
178      * <p>
179      * The returned spliterator effectively allows to slice this segment into disjoint sub-segments, which can then
180      * be processed in parallel by multiple threads.
181      *
182      * @param elementLayout the layout to be used for splitting.
183      * @return the element spliterator for this segment
184      * @throws IllegalArgumentException if the {@code elementLayout} size is zero, or the segment size modulo the
185      * {@code elementLayout} size is greater than zero.
186      */
187     Spliterator<MemorySegment> spliterator(MemoryLayout elementLayout);
188 
189     /**
190      * Returns a sequential {@code Stream} over disjoint slices (whose size matches that of the specified layout)
191      * in this segment. Calling this method is equivalent to the following code:
192      * <blockquote><pre>{@code
193     StreamSupport.stream(segment.spliterator(elementLayout), false);
194      * }</pre></blockquote>
195      *
196      * @param elementLayout the layout to be used for splitting.
197      * @return a sequential {@code Stream} over disjoint slices in this segment.
198      * @throws IllegalArgumentException if the {@code elementLayout} size is zero, or the segment size modulo the
199      * {@code elementLayout} size is greater than zero.
200      */
201     Stream<MemorySegment> elements(MemoryLayout elementLayout);
202 
203     /**
204      * Returns the resource scope associated with this memory segment.
205      * @return the resource scope associated with this memory segment.
206      */
207     ResourceScope scope();
208 
209     /**
210      * The size (in bytes) of this memory segment.
211      * @return The size (in bytes) of this memory segment.
212      */
213     long byteSize();
214 
215     /**
216      * Obtains a new memory segment view whose base address is the same as the base address of this segment plus a given offset,
217      * and whose new size is specified by the given argument.
218      *
219      * @see #asSlice(long)
220      * @see #asSlice(MemoryAddress)
221      * @see #asSlice(MemoryAddress, long)
222      *
223      * @param offset The new segment base offset (relative to the current segment base address), specified in bytes.
224      * @param newSize The new segment size, specified in bytes.
225      * @return a new memory segment view with updated base/limit addresses.
226      * @throws IndexOutOfBoundsException if {@code offset < 0}, {@code offset > byteSize()}, {@code newSize < 0}, or {@code newSize > byteSize() - offset}
227      */
228     MemorySegment asSlice(long offset, long newSize);
229 
230     /**
231      * Obtains a new memory segment view whose base address is the given address, and whose new size is specified by the given argument.
232      * <p>
233      * Equivalent to the following code:
234      * <pre>{@code
235     asSlice(newBase.segmentOffset(this), newSize);
236      * }</pre>
237      *
238      * @see #asSlice(long)
239      * @see #asSlice(MemoryAddress)
240      * @see #asSlice(long, long)
241      *
242      * @param newBase The new segment base address.
243      * @param newSize The new segment size, specified in bytes.
244      * @return a new memory segment view with updated base/limit addresses.
245      * @throws IndexOutOfBoundsException if {@code offset < 0}, {@code offset > byteSize()}, {@code newSize < 0}, or {@code newSize > byteSize() - offset}
246      */
247     default MemorySegment asSlice(MemoryAddress newBase, long newSize) {
248         Objects.requireNonNull(newBase);
249         return asSlice(newBase.segmentOffset(this), newSize);
250     }
251 
252     /**
253      * Obtains a new memory segment view whose base address is the same as the base address of this segment plus a given offset,
254      * and whose new size is computed by subtracting the specified offset from this segment size.
255      * <p>
256      * Equivalent to the following code:
257      * <pre>{@code
258     asSlice(offset, byteSize() - offset);
259      * }</pre>
260      *
261      * @see #asSlice(MemoryAddress)
262      * @see #asSlice(MemoryAddress, long)
263      * @see #asSlice(long, long)
264      *
265      * @param offset The new segment base offset (relative to the current segment base address), specified in bytes.
266      * @return a new memory segment view with updated base/limit addresses.
267      * @throws IndexOutOfBoundsException if {@code offset < 0}, or {@code offset > byteSize()}.
268      */
269     default MemorySegment asSlice(long offset) {
270         return asSlice(offset, byteSize() - offset);
271     }
272 
273     /**
274      * Obtains a new memory segment view whose base address is the given address, and whose new size is computed by subtracting
275      * the address offset relative to this segment (see {@link MemoryAddress#segmentOffset(MemorySegment)}) from this segment size.
276      * <p>
277      * Equivalent to the following code:
278      * <pre>{@code
279     asSlice(newBase.segmentOffset(this));
280      * }</pre>
281      *
282      * @see #asSlice(long)
283      * @see #asSlice(MemoryAddress, long)
284      * @see #asSlice(long, long)
285      *
286      * @param newBase The new segment base offset (relative to the current segment base address), specified in bytes.
287      * @return a new memory segment view with updated base/limit addresses.
288      * @throws IndexOutOfBoundsException if {@code address.segmentOffset(this) < 0}, or {@code address.segmentOffset(this) > byteSize()}.
289      */
290     default MemorySegment asSlice(MemoryAddress newBase) {
291         Objects.requireNonNull(newBase);
292         return asSlice(newBase.segmentOffset(this));
293     }
294 
295     /**
296      * Is this segment read-only?
297      * @return {@code true}, if this segment is read-only.
298      * @see #asReadOnly()
299      */
300     boolean isReadOnly();
301 
302     /**
303      * Obtains a read-only view of this segment. The resulting segment will be identical to this one, but
304      * attempts to overwrite the contents of the returned segment will cause runtime exceptions.
305      * @return a read-only view of this segment
306      * @see #isReadOnly()
307      */
308     MemorySegment asReadOnly();
309 
310     /**
311      * Is this a native segment? Returns true if this segment is a native memory segment,
312      * created using the {@link #allocateNative(long, ResourceScope)} (and related) factory, or a buffer segment
313      * derived from a direct {@link java.nio.ByteBuffer} using the {@link #ofByteBuffer(ByteBuffer)} factory,
314      * or if this is a {@linkplain #isMapped() mapped} segment.
315      * @return {@code true} if this segment is native segment.
316      */
317     boolean isNative();
318 
319     /**
320      * Is this a mapped segment? Returns true if this segment is a mapped memory segment,
321      * created using the {@link #mapFile(Path, long, long, FileChannel.MapMode, ResourceScope)} factory, or a buffer segment
322      * derived from a {@link java.nio.MappedByteBuffer} using the {@link #ofByteBuffer(ByteBuffer)} factory.
323      * @return {@code true} if this segment is a mapped segment.
324      */
325     boolean isMapped();
326 
327     /**
328      * Fills a value into this memory segment.
329      * <p>
330      * More specifically, the given value is filled into each address of this
331      * segment. Equivalent to (but likely more efficient than) the following code:
332      *
333      * <pre>{@code
334 byteHandle = MemoryLayout.ofSequence(MemoryLayouts.JAVA_BYTE)
335          .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
336 for (long l = 0; l < segment.byteSize(); l++) {
337      byteHandle.set(segment.address(), l, value);
338 }
339      * }</pre>
340      *
341      * without any regard or guarantees on the ordering of particular memory
342      * elements being set.
343      * <p>
344      * Fill can be useful to initialize or reset the memory of a segment.
345      *
346      * @param value the value to fill into this segment
347      * @return this memory segment
348      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
349      * a thread other than the thread owning that scope,
350      * @throws UnsupportedOperationException if this segment is read-only (see {@link #isReadOnly()}).
351      */
352     MemorySegment fill(byte value);
353 
354     /**
355      * Performs a bulk copy from given source segment to this segment. More specifically, the bytes at
356      * offset {@code 0} through {@code src.byteSize() - 1} in the source segment are copied into this segment
357      * at offset {@code 0} through {@code src.byteSize() - 1}.
358      * If the source segment overlaps with this segment, then the copying is performed as if the bytes at
359      * offset {@code 0} through {@code src.byteSize() - 1} in the source segment were first copied into a
360      * temporary segment with size {@code bytes}, and then the contents of the temporary segment were copied into
361      * this segment at offset {@code 0} through {@code src.byteSize() - 1}.
362      * <p>
363      * The result of a bulk copy is unspecified if, in the uncommon case, the source segment and this segment
364      * do not overlap, but refer to overlapping regions of the same backing storage using different addresses.
365      * For example, this may occur if the same file is {@linkplain MemorySegment#mapFile mapped} to two segments.
366      *
367      * @param src the source segment.
368      * @throws IndexOutOfBoundsException if {@code src.byteSize() > this.byteSize()}.
369      * @throws IllegalStateException if either the scope associated with the source segment or the scope associated
370      * with this segment have been already closed, or if access occurs from a thread other than the thread owning either
371      * scopes.
372      * @throws UnsupportedOperationException if this segment is read-only (see {@link #isReadOnly()}).
373      */
374     void copyFrom(MemorySegment src);
375 
376     /**
377      * Finds and returns the offset, in bytes, of the first mismatch between
378      * this segment and a given other segment. The offset is relative to the
379      * {@linkplain #address() base address} of each segment and will be in the
380      * range of 0 (inclusive) up to the {@linkplain #byteSize() size} (in bytes) of
381      * the smaller memory segment (exclusive).
382      * <p>
383      * If the two segments share a common prefix then the returned offset is
384      * the length of the common prefix and it follows that there is a mismatch
385      * between the two segments at that offset within the respective segments.
386      * If one segment is a proper prefix of the other then the returned offset is
387      * the smaller of the segment sizes, and it follows that the offset is only
388      * valid for the larger segment. Otherwise, there is no mismatch and {@code
389      * -1} is returned.
390      *
391      * @param other the segment to be tested for a mismatch with this segment
392      * @return the relative offset, in bytes, of the first mismatch between this
393      * and the given other segment, otherwise -1 if no mismatch
394      * @throws IllegalStateException if either the scope associated with this segment or the scope associated
395      * with the {@code other} segment have been already closed, or if access occurs from a thread other than the thread
396      * owning either scopes.
397      */
398     long mismatch(MemorySegment other);
399 
400     /**
401      * Tells whether or not the contents of this mapped segment is resident in physical
402      * memory.
403      *
404      * <p> A return value of {@code true} implies that it is highly likely
405      * that all of the data in this segment is resident in physical memory and
406      * may therefore be accessed without incurring any virtual-memory page
407      * faults or I/O operations.  A return value of {@code false} does not
408      * necessarily imply that this segment's content is not resident in physical
409      * memory.
410      *
411      * <p> The returned value is a hint, rather than a guarantee, because the
412      * underlying operating system may have paged out some of this segment's data
413      * by the time that an invocation of this method returns.  </p>
414      *
415      * @return  {@code true} if it is likely that the contents of this segment
416      *          is resident in physical memory
417      *
418      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
419      * a thread other than the thread owning that scope.
420      * @throws UnsupportedOperationException if this segment is not a mapped memory segment, e.g. if
421      * {@code isMapped() == false}.
422      */
423     boolean isLoaded();
424 
425     /**
426      * Loads the contents of this mapped segment into physical memory.
427      *
428      * <p> This method makes a best effort to ensure that, when it returns,
429      * this contents of this segment is resident in physical memory.  Invoking this
430      * method may cause some number of page faults and I/O operations to
431      * occur. </p>
432      *
433      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
434      * a thread other than the thread owning that scope.
435      * @throws UnsupportedOperationException if this segment is not a mapped memory segment, e.g. if
436      * {@code isMapped() == false}.
437      */
438     void load();
439 
440     /**
441      * Unloads the contents of this mapped segment from physical memory.
442      *
443      * <p> This method makes a best effort to ensure that the contents of this segment are
444      * are no longer resident in physical memory. Accessing this segment's contents
445      * after invoking this method may cause some number of page faults and I/O operations to
446      * occur (as this segment's contents might need to be paged back in). </p>
447      *
448      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
449      * a thread other than the thread owning that scope.
450      * @throws UnsupportedOperationException if this segment is not a mapped memory segment, e.g. if
451      * {@code isMapped() == false}.
452      */
453     void unload();
454 
455     /**
456      * Forces any changes made to the contents of this mapped segment to be written to the
457      * storage device described by the mapped segment's file descriptor.
458      *
459      * <p> If the file descriptor associated with this mapped segment resides on a local storage
460      * device then when this method returns it is guaranteed that all changes
461      * made to this segment since it was created, or since this method was last
462      * invoked, will have been written to that device.
463      *
464      * <p> If the file descriptor associated with this mapped segment does not reside on a local device then
465      * no such guarantee is made.
466      *
467      * <p> If this segment was not mapped in read/write mode ({@link
468      * java.nio.channels.FileChannel.MapMode#READ_WRITE}) then
469      * invoking this method may have no effect. In particular, the
470      * method has no effect for segments mapped in read-only or private
471      * mapping modes. This method may or may not have an effect for
472      * implementation-specific mapping modes.
473      * </p>
474      *
475      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
476      * a thread other than the thread owning that scope.
477      * @throws UnsupportedOperationException if this segment is not a mapped memory segment, e.g. if
478      * {@code isMapped() == false}.
479      * @throws UncheckedIOException if there is an I/O error writing the contents of this segment to the associated storage device
480      */
481     void force();
482 
483     /**
484      * Wraps this segment in a {@link ByteBuffer}. Some of the properties of the returned buffer are linked to
485      * the properties of this segment. For instance, if this segment is <em>immutable</em>
486      * (e.g. the segment is a read-only segment, see {@link #isReadOnly()}), then the resulting buffer is <em>read-only</em>
487      * (see {@link ByteBuffer#isReadOnly()}. Additionally, if this is a native memory segment, the resulting buffer is
488      * <em>direct</em> (see {@link ByteBuffer#isDirect()}).
489      * <p>
490      * The returned buffer's position (see {@link ByteBuffer#position()} is initially set to zero, while
491      * the returned buffer's capacity and limit (see {@link ByteBuffer#capacity()} and {@link ByteBuffer#limit()}, respectively)
492      * are set to this segment' size (see {@link MemorySegment#byteSize()}). For this reason, a byte buffer cannot be
493      * returned if this segment' size is greater than {@link Integer#MAX_VALUE}.
494      * <p>
495      * The life-cycle of the returned buffer will be tied to that of this segment. That is, accessing the returned buffer
496      * after the scope associated with this segment has been closed (see {@link ResourceScope#close()}, will throw an {@link IllegalStateException}.
497      * <p>
498      * If this segment is associated with a confined scope, calling read/write I/O operations on the resulting buffer
499      * might result in an unspecified exception being thrown. Examples of such problematic operations are
500      * {@link java.nio.channels.AsynchronousSocketChannel#read(ByteBuffer)} and
501      * {@link java.nio.channels.AsynchronousSocketChannel#write(ByteBuffer)}.
502      * <p>
503      * Finally, the resulting buffer's byte order is {@link java.nio.ByteOrder#BIG_ENDIAN}; this can be changed using
504      * {@link ByteBuffer#order(java.nio.ByteOrder)}.
505      *
506      * @return a {@link ByteBuffer} view of this memory segment.
507      * @throws UnsupportedOperationException if this segment cannot be mapped onto a {@link ByteBuffer} instance,
508      * e.g. because it models an heap-based segment that is not based on a {@code byte[]}), or if its size is greater
509      * than {@link Integer#MAX_VALUE}.
510      */
511     ByteBuffer asByteBuffer();
512 
513     /**
514      * Copy the contents of this memory segment into a fresh byte array.
515      * @return a fresh byte array copy of this memory segment.
516      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
517      * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link byte[]} instance,
518      * e.g. its size is greater than {@link Integer#MAX_VALUE}.
519      */
520     byte[] toByteArray();
521 
522     /**
523      * Copy the contents of this memory segment into a fresh short array.
524      * @return a fresh short array copy of this memory segment.
525      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
526      * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link short[]} instance,
527      * e.g. because {@code byteSize() % 2 != 0}, or {@code byteSize() / 2 > Integer#MAX_VALUE}
528      */
529     short[] toShortArray();
530 
531     /**
532      * Copy the contents of this memory segment into a fresh char array.
533      * @return a fresh char array copy of this memory segment.
534      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
535      * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link char[]} instance,
536      * e.g. because {@code byteSize() % 2 != 0}, or {@code byteSize() / 2 > Integer#MAX_VALUE}.
537      */
538     char[] toCharArray();
539 
540     /**
541      * Copy the contents of this memory segment into a fresh int array.
542      * @return a fresh int array copy of this memory segment.
543      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
544      * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link int[]} instance,
545      * e.g. because {@code byteSize() % 4 != 0}, or {@code byteSize() / 4 > Integer#MAX_VALUE}.
546      */
547     int[] toIntArray();
548 
549     /**
550      * Copy the contents of this memory segment into a fresh float array.
551      * @return a fresh float array copy of this memory segment.
552      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
553      * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link float[]} instance,
554      * e.g. because {@code byteSize() % 4 != 0}, or {@code byteSize() / 4 > Integer#MAX_VALUE}.
555      */
556     float[] toFloatArray();
557 
558     /**
559      * Copy the contents of this memory segment into a fresh long array.
560      * @return a fresh long array copy of this memory segment.
561      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
562      * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link long[]} instance,
563      * e.g. because {@code byteSize() % 8 != 0}, or {@code byteSize() / 8 > Integer#MAX_VALUE}.
564      */
565     long[] toLongArray();
566 
567     /**
568      * Copy the contents of this memory segment into a fresh double array.
569      * @return a fresh double array copy of this memory segment.
570      * @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
571      * a thread other than the thread owning that scope, or if this segment's contents cannot be copied into a {@link double[]} instance,
572      * e.g. because {@code byteSize() % 8 != 0}, or {@code byteSize() / 8 > Integer#MAX_VALUE}.
573      */
574     double[] toDoubleArray();
575 
576     /**
577      * Creates a new confined buffer memory segment that models the memory associated with the given byte
578      * buffer. The segment starts relative to the buffer's position (inclusive)
579      * and ends relative to the buffer's limit (exclusive).
580      * <p>
581      * If the buffer is {@link ByteBuffer#isReadOnly() read-only}, the resulting segment will also be
582      * {@link ByteBuffer#isReadOnly() read-only}. The scope associated with this segment can either be the
583      * {@linkplain ResourceScope#globalScope() global} resource scope, in case the buffer has been created independently,
584      * or to some other (possibly closeable) resource scope, in case the buffer has been obtained using {@link #asByteBuffer()}.
585      * <p>
586      * The resulting memory segment keeps a reference to the backing buffer, keeping it <em>reachable</em>.
587      *
588      * @param bb the byte buffer backing the buffer memory segment.
589      * @return a new buffer memory segment.
590      */
591     static MemorySegment ofByteBuffer(ByteBuffer bb) {
592         return AbstractMemorySegmentImpl.ofBuffer(bb);
593     }
594 
595     /**
596      * Creates a new confined array memory segment that models the memory associated with a given heap-allocated byte array.
597      * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope.
598      *
599      * @param arr the primitive array backing the array memory segment.
600      * @return a new array memory segment.
601      */
602     static MemorySegment ofArray(byte[] arr) {
603         return HeapMemorySegmentImpl.OfByte.fromArray(arr);
604     }
605 
606     /**
607      * Creates a new confined array memory segment that models the memory associated with a given heap-allocated char array.
608      * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope.
609      *
610      * @param arr the primitive array backing the array memory segment.
611      * @return a new array memory segment.
612      */
613     static MemorySegment ofArray(char[] arr) {
614         return HeapMemorySegmentImpl.OfChar.fromArray(arr);
615     }
616 
617     /**
618      * Creates a new confined array memory segment that models the memory associated with a given heap-allocated short array.
619      * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope.
620      *
621      * @param arr the primitive array backing the array memory segment.
622      * @return a new array memory segment.
623      */
624     static MemorySegment ofArray(short[] arr) {
625         return HeapMemorySegmentImpl.OfShort.fromArray(arr);
626     }
627 
628     /**
629      * Creates a new confined array memory segment that models the memory associated with a given heap-allocated int array.
630      * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope.
631      *
632      * @param arr the primitive array backing the array memory segment.
633      * @return a new array memory segment.
634      */
635     static MemorySegment ofArray(int[] arr) {
636         return HeapMemorySegmentImpl.OfInt.fromArray(arr);
637     }
638 
639     /**
640      * Creates a new confined array memory segment that models the memory associated with a given heap-allocated float array.
641      * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope.
642      *
643      * @param arr the primitive array backing the array memory segment.
644      * @return a new array memory segment.
645      */
646     static MemorySegment ofArray(float[] arr) {
647         return HeapMemorySegmentImpl.OfFloat.fromArray(arr);
648     }
649 
650     /**
651      * Creates a new confined array memory segment that models the memory associated with a given heap-allocated long array.
652      * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope.
653      *
654      * @param arr the primitive array backing the array memory segment.
655      * @return a new array memory segment.
656      */
657     static MemorySegment ofArray(long[] arr) {
658         return HeapMemorySegmentImpl.OfLong.fromArray(arr);
659     }
660 
661     /**
662      * Creates a new confined array memory segment that models the memory associated with a given heap-allocated double array.
663      * The returned segment's resource scope is set to the {@linkplain ResourceScope#globalScope() global} resource scope.
664      *
665      * @param arr the primitive array backing the array memory segment.
666      * @return a new array memory segment.
667      */
668     static MemorySegment ofArray(double[] arr) {
669         return HeapMemorySegmentImpl.OfDouble.fromArray(arr);
670     }
671 
672     /**
673      * Creates a new confined native memory segment that models a newly allocated block of off-heap memory with given layout
674      * and resource scope. A client is responsible make sure that the resource scope associated with the returned segment is closed
675      * when the segment is no longer in use. Failure to do so will result in off-heap memory leaks.
676      * <p>
677      * This is equivalent to the following code:
678      * <blockquote><pre>{@code
679     allocateNative(layout.bytesSize(), layout.bytesAlignment(), scope);
680      * }</pre></blockquote>
681      * <p>
682      * The block of off-heap memory associated with the returned native memory segment is initialized to zero.
683      *
684      * @param layout the layout of the off-heap memory block backing the native memory segment.
685      * @param scope the segment scope.
686      * @return a new native memory segment.
687      * @throws IllegalArgumentException if the specified layout has illegal size or alignment constraint.
688      * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
689      * than the thread owning {@code scope}.
690      */
691     static MemorySegment allocateNative(MemoryLayout layout, ResourceScope scope) {
692         Objects.requireNonNull(scope);
693         Objects.requireNonNull(layout);
694         return allocateNative(layout.byteSize(), layout.byteAlignment(), scope);
695     }
696 
697     /**
698      * Creates a new confined native memory segment that models a newly allocated block of off-heap memory with given size (in bytes)
699      * and resource scope. A client is responsible make sure that the resource scope associated with the returned segment is closed
700      * when the segment is no longer in use. Failure to do so will result in off-heap memory leaks.
701      * <p>
702      * This is equivalent to the following code:
703      * <blockquote><pre>{@code
704     allocateNative(bytesSize, 1, scope);
705      * }</pre></blockquote>
706      * <p>
707      * The block of off-heap memory associated with the returned native memory segment is initialized to zero.
708      *
709      * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment.
710      * @param scope the segment scope.
711      * @return a new native memory segment.
712      * @throws IllegalArgumentException if {@code bytesSize <= 0}.
713      * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
714      * than the thread owning {@code scope}.
715      */
716     static MemorySegment allocateNative(long bytesSize, ResourceScope scope) {
717         return allocateNative(bytesSize, 1, scope);
718     }
719 
720     /**
721      * Creates a new confined native memory segment that models a newly allocated block of off-heap memory with given size
722      * (in bytes), alignment constraint (in bytes) and resource scope. A client is responsible make sure that the resource
723      * scope associated with the returned segment is closed when the segment is no longer in use.
724      * Failure to do so will result in off-heap memory leaks.
725      * <p>
726      * The block of off-heap memory associated with the returned native memory segment is initialized to zero.
727      *
728      * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment.
729      * @param alignmentBytes the alignment constraint (in bytes) of the off-heap memory block backing the native memory segment.
730      * @param scope the segment scope.
731      * @return a new native memory segment.
732      * @throws IllegalArgumentException if {@code bytesSize <= 0}, {@code alignmentBytes <= 0}, or if {@code alignmentBytes}
733      * is not a power of 2.
734      * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
735      * than the thread owning {@code scope}.
736      */
737     static MemorySegment allocateNative(long bytesSize, long alignmentBytes, ResourceScope scope) {
738         Objects.requireNonNull(scope);
739         if (bytesSize <= 0) {
740             throw new IllegalArgumentException("Invalid allocation size : " + bytesSize);
741         }
742 
743         if (alignmentBytes <= 0 ||
744                 ((alignmentBytes & (alignmentBytes - 1)) != 0L)) {
745             throw new IllegalArgumentException("Invalid alignment constraint : " + alignmentBytes);
746         }
747 
748         return NativeMemorySegmentImpl.makeNativeSegment(bytesSize, alignmentBytes, (ResourceScopeImpl) scope);
749     }
750 
751     /**
752      * Creates a new mapped memory segment that models a memory-mapped region of a file from a given path.
753      * <p>
754      * If the specified mapping mode is {@linkplain FileChannel.MapMode#READ_ONLY READ_ONLY}, the resulting segment
755      * will be read-only (see {@link #isReadOnly()}).
756      * <p>
757      * The content of a mapped memory segment can change at any time, for example
758      * if the content of the corresponding region of the mapped file is changed by
759      * this (or another) program.  Whether or not such changes occur, and when they
760      * occur, is operating-system dependent and therefore unspecified.
761      * <p>
762      * All or part of a mapped memory segment may become
763      * inaccessible at any time, for example if the backing mapped file is truncated.  An
764      * attempt to access an inaccessible region of a mapped memory segment will not
765      * change the segment's content and will cause an unspecified exception to be
766      * thrown either at the time of the access or at some later time.  It is
767      * therefore strongly recommended that appropriate precautions be taken to
768      * avoid the manipulation of a mapped file by this (or another) program, except to read or write
769      * the file's content.
770      *
771      * @implNote When obtaining a mapped segment from a newly created file, the initialization state of the contents of the block
772      * of mapped memory associated with the returned mapped memory segment is unspecified and should not be relied upon.
773      *
774      * @param path the path to the file to memory map.
775      * @param bytesOffset the offset (expressed in bytes) within the file at which the mapped segment is to start.
776      * @param bytesSize the size (in bytes) of the mapped memory backing the memory segment.
777      * @param mapMode a file mapping mode, see {@link FileChannel#map(FileChannel.MapMode, long, long)}; the chosen mapping mode
778      *                might affect the behavior of the returned memory mapped segment (see {@link #force()}).
779      * @param scope the segment scope.
780      * @return a new confined mapped memory segment.
781      * @throws IllegalArgumentException if {@code bytesOffset < 0}, {@code bytesSize < 0}, or if {@code path} is not associated
782      * with the default file system.
783      * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
784      * than the thread owning {@code scope}.
785      * @throws UnsupportedOperationException if an unsupported map mode is specified.
786      * @throws IOException if the specified path does not point to an existing file, or if some other I/O error occurs.
787      * @throws  SecurityException If a security manager is installed and it denies an unspecified permission required by the implementation.
788      * In the case of the default provider, the {@link SecurityManager#checkRead(String)} method is invoked to check
789      * read access if the file is opened for reading. The {@link SecurityManager#checkWrite(String)} method is invoked to check
790      * write access if the file is opened for writing.
791      */
792     static MemorySegment mapFile(Path path, long bytesOffset, long bytesSize, FileChannel.MapMode mapMode, ResourceScope scope) throws IOException {
793         Objects.requireNonNull(scope);
794         return MappedMemorySegmentImpl.makeMappedSegment(path, bytesOffset, bytesSize, mapMode, (ResourceScopeImpl) scope);
795     }
796 
797     /**
798      * Returns a native memory segment whose base address is {@link MemoryAddress#NULL} and whose size is {@link Long#MAX_VALUE}.
799      * This method can be very useful when dereferencing memory addresses obtained when interacting with native libraries.
800      * The returned segment is associated with the <em>global</em> resource scope (see {@link ResourceScope#globalScope()}).
801      * Equivalent to (but likely more efficient than) the following code:
802      * <pre>{@code
803     MemoryAddress.NULL.asSegment(Long.MAX_VALUE)
804      * }</pre>
805      * <p>
806      * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
807      * Restricted methods are unsafe, and, if used incorrectly, their use might crash
808      * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
809      * restricted methods, and use safe and supported functionalities, where possible.
810      *
811      * @return a memory segment whose base address is {@link MemoryAddress#NULL} and whose size is {@link Long#MAX_VALUE}.
812      * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
813      * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
814      * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
815      */
816     @CallerSensitive
817     static MemorySegment globalNativeSegment() {
818         Reflection.ensureNativeAccess(Reflection.getCallerClass());
819         return NativeMemorySegmentImpl.EVERYTHING;
820     }
821 }