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 }