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