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 SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.ofSequence(1024, MemoryLayouts.JAVA_INT);
114 VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
115 int sum = StreamSupport.stream(segment.spliterator(SEQUENCE_LAYOUT), true)
116 .mapToInt(segment -> (int)VH_int.get(segment.baseAddress))
117 .sum();
118 * }</pre></blockquote>
119 *
120 * <h2><a id = "access-modes">Access modes</a></h2>
121 *
122 * Memory segments supports zero or more <em>access modes</em>. Supported access modes are {@link #READ},
123 * {@link #WRITE}, {@link #CLOSE} and {@link #ACQUIRE}. The set of access modes supported by a segment alters the
124 * set of operations that are supported by that segment. For instance, attempting to call {@link #close()} on
125 * a segment which does not support the {@link #CLOSE} access mode will result in an exception.
126 * <p>
127 * The set of supported access modes can only be made stricter (by supporting <em>less</em> access modes). This means
128 * that restricting the set of access modes supported by a segment before sharing it with other clients
129 * is generally a good practice if the creator of the segment wants to retain some control over how the segment
130 * is going to be accessed.
131 *
132 * <h2>Memory segment views</h2>
133 *
134 * Memory segments support <em>views</em>. For instance, it is possible to alter the set of supported access modes,
135 * by creating an <em>immutable</em> view of a memory segment, as follows:
136 * <blockquote><pre>{@code
137 MemorySegment segment = ...
138 MemorySegment roSegment = segment.withAccessModes(segment.accessModes() & ~WRITE);
139 * }</pre></blockquote>
140 * It is also possible to create views whose spatial bounds are stricter than the ones of the original segment
141 * (see {@link MemorySegment#asSlice(long, long)}).
142 * <p>
143 * Temporal bounds of the original segment are inherited by the view; that is, closing a segment view, such as a sliced
144 * view, will cause the original segment to be closed; as such special care must be taken when sharing views
145 * between multiple clients. If a client want to protect itself against early closure of a segment by
146 * another actor, it is the responsibility of that client to take protective measures, such as removing {@link #CLOSE}
147 * from the set of supported access modes, before sharing the view with another client.
148 * <p>
149 * To allow for interoperability with existing code, a byte buffer view can be obtained from a memory segment
150 * (see {@link #asByteBuffer()}). This can be useful, for instance, for those clients that want to keep using the
151 * {@link ByteBuffer} API, but need to operate on large memory segments. Byte buffers obtained in such a way support
152 * the same spatial and temporal access restrictions associated to the memory address from which they originated.
153 *
154 * @apiNote In the future, if the Java language permits, {@link MemorySegment}
155 * may become a {@code sealed} interface, which would prohibit subclassing except by
156 * {@link MappedMemorySegment} and other explicitly permitted subtypes.
157 *
158 * @implSpec
159 * Implementations of this interface are immutable and thread-safe.
160 */
161 public interface MemorySegment extends AutoCloseable {
162
163 /**
164 * The base memory address associated with this memory segment. The returned address is
165 * a <em>checked</em> memory address and can therefore be used in derefrence operations
166 * (see {@link MemoryAddress}).
167 * @return The base memory address.
168 */
169 MemoryAddress baseAddress();
170
171 /**
172 * Returns a spliterator for the given memory segment. The returned spliterator reports {@link Spliterator#SIZED},
173 * {@link Spliterator#SUBSIZED}, {@link Spliterator#IMMUTABLE}, {@link Spliterator#NONNULL} and {@link Spliterator#ORDERED}
174 * characteristics.
175 * <p>
176 * The returned spliterator splits the segment according to the specified sequence layout; that is,
177 * if the supplied layout is a sequence layout whose element count is {@code N}, then calling {@link Spliterator#trySplit()}
178 * will result in a spliterator serving approximatively {@code N/2} elements (depending on whether N is even or not).
179 * As such, splitting is possible as long as {@code N >= 2}.
180 * <p>
181 * The returned spliterator effectively allows to slice a segment into disjoint sub-segments, which can then
182 * be processed in parallel by multiple threads (if the access mode {@link #ACQUIRE} is set).
183 * While closing the segment (see {@link #close()}) during pending concurrent execution will generally
184 * fail with an exception, it is possible to close a segment when a spliterator has been obtained but no thread
185 * is actively working on it using {@link Spliterator#tryAdvance(Consumer)}; in such cases, any subsequent call
186 * to {@link Spliterator#tryAdvance(Consumer)} will fail with an exception.
187 * @param segment the segment to be used for splitting.
188 * @param layout the layout to be used for splitting.
189 * @param <S> the memory segment type
190 * @return the element spliterator for this segment
191 * @throws IllegalStateException if the segment is not <em>alive</em>, or if access occurs from a thread other than the
192 * thread owning this segment
193 */
194 static <S extends MemorySegment> Spliterator<S> spliterator(S segment, SequenceLayout layout) {
195 return AbstractMemorySegmentImpl.spliterator(segment, layout);
196 }
197
198 /**
199 * The thread owning this segment.
200 * @return the thread owning this segment.
201 */
202 Thread ownerThread();
203
204 /**
205 * Obtains a new memory segment backed by the same underlying memory region as this segment,
206 * but with different owner thread. As a side-effect, this segment will be marked as <em>not alive</em>,
207 * and subsequent operations on this segment will result in runtime errors.
208 * <p>
209 * Write accesses to the segment's content <a href="../../../java/util/concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
210 * 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
211 * the new owner thread.
212 *
213 * @param newOwner the new owner thread.
214 * @return a new memory segment backed by the same underlying memory region as this segment,
215 * owned by {@code newOwner}.
216 * @throws IllegalStateException if this segment is not <em>alive</em>, or if access occurs from a thread other than the
217 * thread owning this segment, or if the segment cannot be closed because it is being operated upon by a different
218 * thread (see {@link #spliterator(SequenceLayout)}).
219 * @throws NullPointerException if {@code newOwner == null}
220 * @throws IllegalArgumentException if the segment is already a confined segment owner by {@code newOnwer}.
221 * @throws UnsupportedOperationException if this segment does not support the {@link #HANDOFF} access mode.
222 */
223 MemorySegment withOwnerThread(Thread newOwner);
224
225 /**
226 * The size (in bytes) of this memory segment.
227 * @return The size (in bytes) of this memory segment.
228 */
229 long byteSize();
230
231 /**
232 * Obtains a segment view with specific <a href="#access-modes">access modes</a>. Supported access modes are {@link #READ}, {@link #WRITE},
233 * {@link #CLOSE} and {@link #ACQUIRE}. It is generally not possible to go from a segment with stricter access modes
234 * to one with less strict access modes. For instance, attempting to add {@link #WRITE} access mode to a read-only segment
235 * will be met with an exception.
236 * @param accessModes an ORed mask of zero or more access modes.
237 * @return a segment view with specific access modes.
238 * @throws UnsupportedOperationException when {@code mask} is an access mask which is less strict than the one supported by this
239 * segment.
240 */
241 MemorySegment withAccessModes(int accessModes);
242
243 /**
244 * Does this segment support a given set of access modes?
245 * @param accessModes an ORed mask of zero or more access modes.
246 * @return true, if the access modes in {@code accessModes} are stricter than the ones supported by this segment.
247 */
248 boolean hasAccessModes(int accessModes);
249
250 /**
251 * Returns the <a href="#access-modes">access modes</a> associated with this segment; the result is represented as ORed values from
252 * {@link #READ}, {@link #WRITE}, {@link #CLOSE} and {@link #ACQUIRE}.
253 * @return the access modes associated with this segment.
254 */
255 int accessModes();
256
257 /**
258 * Obtains a new memory segment view whose base address is the same as the base address of this segment plus a given offset,
259 * and whose new size is specified by the given argument.
260 * @param offset The new segment base offset (relative to the current segment base address), specified in bytes.
261 * @param newSize The new segment size, specified in bytes.
262 * @return a new memory segment view with updated base/limit addresses.
263 * @throws IndexOutOfBoundsException if {@code offset < 0}, {@code offset > byteSize()}, {@code newSize < 0}, or {@code newSize > byteSize() - offset}
264 */
265 MemorySegment asSlice(long offset, long newSize);
266
267 /**
268 * Is this segment alive?
269 * @return true, if the segment is alive.
270 * @see MemorySegment#close()
271 */
272 boolean isAlive();
273
274 /**
275 * Closes this memory segment. Once a memory segment has been closed, any attempt to use the memory segment,
276 * or to access the memory associated with the segment will fail with {@link IllegalStateException}. Depending on
277 * the kind of memory segment being closed, calling this method further trigger deallocation of all the resources
278 * associated with the memory segment.
279 * @throws IllegalStateException if this segment is not <em>alive</em>, or if access occurs from a thread other than the
280 * thread owning this segment, or if the segment cannot be closed because it is being operated upon by a different
281 * thread (see {@link #spliterator(MemorySegment, SequenceLayout)}).
282 * @throws UnsupportedOperationException if this segment does not support the {@link #CLOSE} access mode.
283 */
284 void close();
285
286 /**
287 * Fills a value into this memory segment.
288 * <p>
289 * More specifically, the given value is filled into each address of this
290 * segment. Equivalent to (but likely more efficient than) the following code:
291 *
292 * <blockquote><pre>
293 * byteHandle = MemoryLayout.ofSequence(MemoryLayouts.JAVA_BYTE)
294 * .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
295 * for (long l = 0; l < segment.byteSize(); l++) {
296 * byteHandle.set(segment.baseAddress(), l, value);
297 * }</pre></blockquote>
298 * without any regard or guarantees on the ordering of particular memory
299 * elements being set.
300 * <p>
301 * Fill can be useful to initialize or reset the memory of a segment.
302 *
303 * @param value the value to fill into this segment
304 * @return this memory segment
305 * @throws IllegalStateException if this segment is not <em>alive</em>, or if access occurs from a thread other than the
306 * thread owning this segment
307 * @throws UnsupportedOperationException if this segment does not support the {@link #WRITE} access mode
308 */
309 MemorySegment fill(byte value);
310
311 /**
312 * Wraps this segment in a {@link ByteBuffer}. Some of the properties of the returned buffer are linked to
313 * the properties of this segment. For instance, if this segment is <em>immutable</em>
314 * (e.g. the segment has access mode {@link #READ} but not {@link #WRITE}), then the resulting buffer is <em>read-only</em>
315 * (see {@link ByteBuffer#isReadOnly()}. Additionally, if this is a native memory segment, the resulting buffer is
316 * <em>direct</em> (see {@link ByteBuffer#isDirect()}).
317 * <p>
318 * The life-cycle of the returned buffer will be tied to that of this segment. That means that if the this segment
319 * is closed (see {@link MemorySegment#close()}, accessing the returned
320 * buffer will throw an {@link IllegalStateException}.
321 * <p>
322 * The resulting buffer's byte order is {@link java.nio.ByteOrder#BIG_ENDIAN}; this can be changed using
323 * {@link ByteBuffer#order(java.nio.ByteOrder)}.
324 *
325 * @return a {@link ByteBuffer} view of this memory segment.
326 * @throws UnsupportedOperationException if this segment cannot be mapped onto a {@link ByteBuffer} instance,
327 * e.g. because it models an heap-based segment that is not based on a {@code byte[]}), or if its size is greater
328 * than {@link Integer#MAX_VALUE}, or if the segment does not support the {@link #READ} access mode.
329 */
330 ByteBuffer asByteBuffer();
331
332 /**
333 * Copy the contents of this memory segment into a fresh byte array.
334 * @return a fresh byte array copy of this memory segment.
335 * @throws UnsupportedOperationException if this segment's contents cannot be copied into a {@link byte[]} instance,
336 * e.g. its size is greater than {@link Integer#MAX_VALUE}.
337 * @throws IllegalStateException if this segment has been closed, or if access occurs from a thread other than the
338 * thread owning this segment.
339 */
340 byte[] toByteArray();
341
342 /**
343 * Creates a new buffer memory segment that models the memory associated with the given byte
344 * buffer. The segment starts relative to the buffer's position (inclusive)
345 * and ends relative to the buffer's limit (exclusive).
346 * <p>
347 * The resulting memory segment keeps a reference to the backing buffer, to ensure it remains <em>reachable</em>
348 * for the life-time of the segment.
349 *
350 * @param bb the byte buffer backing the buffer memory segment.
351 * @return a new buffer memory segment.
352 */
353 static MemorySegment ofByteBuffer(ByteBuffer bb) {
354 return AbstractMemorySegmentImpl.ofBuffer(bb);
355 }
356
357 /**
358 * Creates a new array memory segment that models the memory associated with a given heap-allocated byte array.
359 * <p>
360 * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
361 * for the life-time of the segment.
362 *
363 * @param arr the primitive array backing the array memory segment.
364 * @return a new array memory segment.
365 */
366 static MemorySegment ofArray(byte[] arr) {
367 return HeapMemorySegmentImpl.makeArraySegment(arr);
368 }
369
370 /**
371 * Creates a new array memory segment that models the memory associated with a given heap-allocated char array.
372 * <p>
373 * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
374 * for the life-time of the segment.
375 *
376 * @param arr the primitive array backing the array memory segment.
377 * @return a new array memory segment.
378 */
379 static MemorySegment ofArray(char[] arr) {
380 return HeapMemorySegmentImpl.makeArraySegment(arr);
381 }
382
383 /**
384 * Creates a new array memory segment that models the memory associated with a given heap-allocated short array.
385 * <p>
386 * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
387 * for the life-time of the segment.
388 *
389 * @param arr the primitive array backing the array memory segment.
390 * @return a new array memory segment.
391 */
392 static MemorySegment ofArray(short[] arr) {
393 return HeapMemorySegmentImpl.makeArraySegment(arr);
394 }
395
396 /**
397 * Creates a new array memory segment that models the memory associated with a given heap-allocated int array.
398 * <p>
399 * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
400 * for the life-time of the segment.
401 *
402 * @param arr the primitive array backing the array memory segment.
403 * @return a new array memory segment.
404 */
405 static MemorySegment ofArray(int[] arr) {
406 return HeapMemorySegmentImpl.makeArraySegment(arr);
407 }
408
409 /**
410 * Creates a new array memory segment that models the memory associated with a given heap-allocated float array.
411 * <p>
412 * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
413 * for the life-time of the segment.
414 *
415 * @param arr the primitive array backing the array memory segment.
416 * @return a new array memory segment.
417 */
418 static MemorySegment ofArray(float[] arr) {
419 return HeapMemorySegmentImpl.makeArraySegment(arr);
420 }
421
422 /**
423 * Creates a new array memory segment that models the memory associated with a given heap-allocated long array.
424 * <p>
425 * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
426 * for the life-time of the segment.
427 *
428 * @param arr the primitive array backing the array memory segment.
429 * @return a new array memory segment.
430 */
431 static MemorySegment ofArray(long[] arr) {
432 return HeapMemorySegmentImpl.makeArraySegment(arr);
433 }
434
435 /**
436 * Creates a new array memory segment that models the memory associated with a given heap-allocated double array.
437 * <p>
438 * The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
439 * for the life-time of the segment.
440 *
441 * @param arr the primitive array backing the array memory segment.
442 * @return a new array memory segment.
443 */
444 static MemorySegment ofArray(double[] arr) {
445 return HeapMemorySegmentImpl.makeArraySegment(arr);
446 }
447
448 /**
449 * Creates a new native memory segment that models a newly allocated block of off-heap memory with given layout.
450 * <p>
451 * This is equivalent to the following code:
452 * <blockquote><pre>{@code
453 allocateNative(layout.bytesSize(), layout.bytesAlignment());
454 * }</pre></blockquote>
455 *
456 * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
457 * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
458 * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
459 *
460 * @param layout the layout of the off-heap memory block backing the native memory segment.
461 * @return a new native memory segment.
462 * @throws IllegalArgumentException if the specified layout has illegal size or alignment constraint.
463 */
464 static MemorySegment allocateNative(MemoryLayout layout) {
465 return allocateNative(layout.byteSize(), layout.byteAlignment());
466 }
467
468 /**
469 * Creates a new native memory segment that models a newly allocated block of off-heap memory with given size (in bytes).
470 * <p>
471 * This is equivalent to the following code:
472 * <blockquote><pre>{@code
473 allocateNative(bytesSize, 1);
474 * }</pre></blockquote>
475 *
476 * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
477 * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
478 * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
479 *
480 * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment.
481 * @return a new native memory segment.
482 * @throws IllegalArgumentException if {@code bytesSize < 0}.
483 */
484 static MemorySegment allocateNative(long bytesSize) {
485 return allocateNative(bytesSize, 1);
486 }
487
488 /**
489 * Creates a new mapped memory segment that models a memory-mapped region of a file from a given path.
490 *
491 * @implNote When obtaining a mapped segment from a newly created file, the initialization state of the contents of the block
492 * of mapped memory associated with the returned mapped memory segment is unspecified and should not be relied upon.
493 *
494 * @param path the path to the file to memory map.
495 * @param bytesSize the size (in bytes) of the mapped memory backing the memory segment.
496 * @param mapMode a file mapping mode, see {@link FileChannel#map(FileChannel.MapMode, long, long)}; the chosen mapping mode
497 * might affect the behavior of the returned memory mapped segment (see {@link MappedMemorySegment#force()}).
498 * @return a new mapped memory segment.
499 * @throws IllegalArgumentException if {@code bytesSize < 0}.
500 * @throws UnsupportedOperationException if an unsupported map mode is specified.
501 * @throws IOException if the specified path does not point to an existing file, or if some other I/O error occurs.
502 */
503 static MappedMemorySegment mapFromPath(Path path, long bytesSize, FileChannel.MapMode mapMode) throws IOException {
504 return MappedMemorySegmentImpl.makeMappedSegment(path, bytesSize, mapMode);
505 }
506
507 /**
508 * Creates a new native memory segment that models a newly allocated block of off-heap memory with given size and
509 * alignment constraint (in bytes).
510 *
511 * @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
512 * Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
513 * to make sure the backing off-heap memory block is deallocated accordingly. Failure to do so will result in off-heap memory leaks.
514 *
515 * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment.
516 * @param alignmentBytes the alignment constraint (in bytes) of the off-heap memory block backing the native memory segment.
517 * @return a new native memory segment.
518 * @throws IllegalArgumentException if {@code bytesSize < 0}, {@code alignmentBytes < 0}, or if {@code alignmentBytes}
519 * is not a power of 2.
520 */
521 static MemorySegment allocateNative(long bytesSize, long alignmentBytes) {
522 if (bytesSize <= 0) {
523 throw new IllegalArgumentException("Invalid allocation size : " + bytesSize);
524 }
525
526 if (alignmentBytes < 0 ||
527 ((alignmentBytes & (alignmentBytes - 1)) != 0L)) {
528 throw new IllegalArgumentException("Invalid alignment constraint : " + alignmentBytes);
529 }
530
531 return NativeMemorySegmentImpl.makeNativeSegment(bytesSize, alignmentBytes);
532 }
533
534 /**
535 * Returns a new native memory segment with given base address and size; the returned segment has its own temporal
536 * bounds, and can therefore be closed; closing such a segment can optionally result in calling an user-provided cleanup
537 * action. This method can be very useful when interacting with custom native memory sources (e.g. custom allocators,
538 * GPU memory, etc.), where an address to some underlying memory region is typically obtained from native code
539 * (often as a plain {@code long} value).
540 * <p>
541 * This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
542 * the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
543 * restricted methods, and use safe and supported functionalities, where possible.
544 *
545 * @param addr the desired base address
546 * @param bytesSize the desired size.
547 * @param owner the desired owner thread. If {@code owner == null}, the returned segment is <em>not</em> confined.
548 * @param cleanup a cleanup action to be executed when the {@link MemorySegment#close()} method is called on the
549 * returned segment. If {@code cleanup == null}, no cleanup action is executed.
550 * @param attachment an object that must be kept alive by the returned segment; this can be useful when
551 * the returned segment depends on memory which could be released if a certain object
552 * is determined to be unreacheable. In most cases this will be set to {@code null}.
553 * @return a new native memory segment with given base address, size, owner, cleanup action and object attachment.
554 * @throws IllegalArgumentException if {@code bytesSize <= 0}.
555 * @throws UnsupportedOperationException if {@code addr} is associated with an heap segment.
556 * @throws IllegalAccessError if the runtime property {@code foreign.restricted} is not set to either
557 * {@code permit}, {@code warn} or {@code debug} (the default value is set to {@code deny}).
558 * @throws NullPointerException if {@code addr == null}.
559 */
560 static MemorySegment ofNativeRestricted(MemoryAddress addr, long bytesSize, Thread owner, Runnable cleanup, Object attachment) {
561 Objects.requireNonNull(addr);
562 if (bytesSize <= 0) {
563 throw new IllegalArgumentException("Invalid size : " + bytesSize);
564 }
565 Utils.checkRestrictedAccess("MemorySegment.ofNativeRestricted");
566 return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, bytesSize, owner, cleanup, attachment);
567 }
568
569 // access mode masks
570
571 /**
572 * Read access mode; read operations are supported by a segment which supports this access mode.
573 * @see MemorySegment#accessModes()
574 * @see MemorySegment#withAccessModes(int)
575 */
576 int READ = 1;
577
578 /**
579 * Write access mode; write operations are supported by a segment which supports this access mode.
580 * @see MemorySegment#accessModes()
581 * @see MemorySegment#withAccessModes(int)
582 */
583 int WRITE = READ << 1;
584
585 /**
586 * Close access mode; calling {@link #close()} is supported by a segment which supports this access mode.
587 * @see MemorySegment#accessModes()
588 * @see MemorySegment#withAccessModes(int)
589 */
590 int CLOSE = WRITE << 1;
591
592 /**
593 * Acquire access mode; this segment support sharing with threads other than the owner thread, via spliterator
594 * (see {@link #spliterator(MemorySegment, SequenceLayout)}).
595 * @see MemorySegment#accessModes()
596 * @see MemorySegment#withAccessModes(int)
597 */
598 int ACQUIRE = CLOSE << 1;
599
600 /**
601 * Handoff access mode; this segment support serial thread-confinement via thread ownership changes
602 * (see {@link #withOwnerThread(Thread)}).
603 * @see MemorySegment#accessModes()
604 * @see MemorySegment#withAccessModes(int)
605 */
606 int HANDOFF = ACQUIRE << 1;
607 }