8308281: Java snippets in the FFM API need to be updated
Reviewed-by: mcimadamore
This commit is contained in:
parent
26227a6ff8
commit
eb11508eff
@ -48,7 +48,7 @@ import java.lang.foreign.MemorySegment.Scope;
|
|||||||
* accessible and their backing regions of memory are never deallocated. Moreover, memory segments allocated with the
|
* accessible and their backing regions of memory are never deallocated. Moreover, memory segments allocated with the
|
||||||
* global arena can be {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} from any thread.
|
* global arena can be {@linkplain MemorySegment#isAccessibleBy(Thread) accessed} from any thread.
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* MemorySegment segment = Arena.global().allocate(100, 1);
|
* MemorySegment segment = Arena.global().allocate(100, 1); // @highlight regex='global()'
|
||||||
* ...
|
* ...
|
||||||
* // segment is never deallocated!
|
* // segment is never deallocated!
|
||||||
*}
|
*}
|
||||||
@ -58,9 +58,8 @@ import java.lang.foreign.MemorySegment.Scope;
|
|||||||
* of memory backing memory segments allocated with the automatic arena are deallocated at some unspecified time
|
* of memory backing memory segments allocated with the automatic arena are deallocated at some unspecified time
|
||||||
* <em>after</em> the automatic arena (and all the segments allocated by it) become
|
* <em>after</em> the automatic arena (and all the segments allocated by it) become
|
||||||
* <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>, as shown below:
|
* <a href="../../../java/lang/ref/package.html#reachability">unreachable</a>, as shown below:
|
||||||
*
|
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* MemorySegment segment = Arena.ofAuto().allocate(100, 1);
|
* MemorySegment segment = Arena.ofAuto().allocate(100, 1); // @highlight regex='ofAuto()'
|
||||||
* ...
|
* ...
|
||||||
* segment = null; // the segment region becomes available for deallocation after this point
|
* segment = null; // the segment region becomes available for deallocation after this point
|
||||||
*}
|
*}
|
||||||
@ -77,7 +76,7 @@ import java.lang.foreign.MemorySegment.Scope;
|
|||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* MemorySegment segment = null;
|
* MemorySegment segment = null;
|
||||||
* try (Arena arena = Arena.ofConfined()) {
|
* try (Arena arena = Arena.ofConfined()) { // @highlight regex='ofConfined()'
|
||||||
* segment = arena.allocate(100);
|
* segment = arena.allocate(100);
|
||||||
* ...
|
* ...
|
||||||
* } // segment region deallocated here
|
* } // segment region deallocated here
|
||||||
@ -157,24 +156,25 @@ import java.lang.foreign.MemorySegment.Scope;
|
|||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* class SlicingArena implements Arena {
|
* class SlicingArena implements Arena {
|
||||||
* final Arena arena = Arena.ofConfined();
|
* final Arena arena = Arena.ofConfined();
|
||||||
* final SegmentAllocator slicingAllocator;
|
* final SegmentAllocator slicingAllocator;
|
||||||
*
|
*
|
||||||
* SlicingArena(long size) {
|
* SlicingArena(long size) {
|
||||||
* slicingAllocator = SegmentAllocator.slicingAllocator(arena.allocate(size));
|
* slicingAllocator = SegmentAllocator.slicingAllocator(arena.allocate(size));
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public void allocate(long byteSize, long byteAlignment) {
|
* public MemorySegment allocate(long byteSize, long byteAlignment) {
|
||||||
* return slicingAllocator.allocate(byteSize, byteAlignment);
|
* return slicingAllocator.allocate(byteSize, byteAlignment);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public MemorySegment.Scope scope() {
|
* public MemorySegment.Scope scope() {
|
||||||
* return arena.scope();
|
* return arena.scope();
|
||||||
* }
|
* }
|
||||||
|
*
|
||||||
|
* public void close() {
|
||||||
|
* arena.close();
|
||||||
|
* }
|
||||||
*
|
*
|
||||||
* public void close() {
|
|
||||||
* return arena.close();
|
|
||||||
* }
|
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
@ -183,10 +183,10 @@ import java.lang.foreign.MemorySegment.Scope;
|
|||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* try (Arena slicingArena = new SlicingArena(1000)) {
|
* try (Arena slicingArena = new SlicingArena(1000)) {
|
||||||
* for (int i = 0 ; i < 10 ; i++) {
|
* for (int i = 0; i < 10; i++) {
|
||||||
* MemorySegment s = slicingArena.allocateArray(JAVA_INT, 1, 2, 3, 4, 5);
|
* MemorySegment s = slicingArena.allocateArray(JAVA_INT, 1, 2, 3, 4, 5);
|
||||||
* ...
|
* ...
|
||||||
* }
|
* }
|
||||||
* } // all memory allocated is released here
|
* } // all memory allocated is released here
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
@ -253,8 +253,8 @@ public interface Arena extends SegmentAllocator, AutoCloseable {
|
|||||||
* {@code S1, S2} returned by this method, the following invariant must hold:
|
* {@code S1, S2} returned by this method, the following invariant must hold:
|
||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* S1.overlappingSlice(S2).isEmpty() == true
|
* S1.asOverlappingSlice(S2).isEmpty() == true
|
||||||
*}
|
* }
|
||||||
*
|
*
|
||||||
* @param byteSize the size (in bytes) of the off-heap memory block backing the native memory segment.
|
* @param byteSize the size (in bytes) of the off-heap memory block backing the native memory segment.
|
||||||
* @param byteAlignment the alignment constraint (in bytes) of the off-heap region of memory backing the native memory segment.
|
* @param byteAlignment the alignment constraint (in bytes) of the off-heap region of memory backing the native memory segment.
|
||||||
|
@ -77,7 +77,7 @@ import java.util.stream.Stream;
|
|||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* Linker linker = Linker.nativeLinker();
|
* Linker linker = Linker.nativeLinker();
|
||||||
* MethodHandle strlen = linker.downcallHandle(
|
* MethodHandle strlen = linker.downcallHandle(
|
||||||
* linker.defaultLookup().find("strlen").get(),
|
* linker.defaultLookup().find("strlen").orElseThrow(),
|
||||||
* FunctionDescriptor.of(JAVA_LONG, ADDRESS)
|
* FunctionDescriptor.of(JAVA_LONG, ADDRESS)
|
||||||
* );
|
* );
|
||||||
* }
|
* }
|
||||||
@ -91,9 +91,9 @@ import java.util.stream.Stream;
|
|||||||
* The obtained downcall method handle is then invoked as follows:
|
* The obtained downcall method handle is then invoked as follows:
|
||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* try (Arena arena = Arena.openConfined()) {
|
* try (Arena arena = Arena.ofConfined()) {
|
||||||
* MemorySegment str = arena.allocateUtf8String("Hello");
|
* MemorySegment str = arena.allocateUtf8String("Hello");
|
||||||
* long len = strlen.invoke(str); // 5
|
* long len = (long) strlen.invokeExact(str); // 5
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* <h3 id="describing-c-sigs">Describing C signatures</h3>
|
* <h3 id="describing-c-sigs">Describing C signatures</h3>
|
||||||
@ -226,7 +226,7 @@ import java.util.stream.Stream;
|
|||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* Linker linker = Linker.nativeLinker();
|
* Linker linker = Linker.nativeLinker();
|
||||||
* MethodHandle qsort = linker.downcallHandle(
|
* MethodHandle qsort = linker.downcallHandle(
|
||||||
* linker.defaultLookup().find("qsort").get(),
|
* linker.defaultLookup().find("qsort").orElseThrow(),
|
||||||
* FunctionDescriptor.ofVoid(ADDRESS, JAVA_LONG, JAVA_LONG, ADDRESS)
|
* FunctionDescriptor.ofVoid(ADDRESS, JAVA_LONG, JAVA_LONG, ADDRESS)
|
||||||
* );
|
* );
|
||||||
* }
|
* }
|
||||||
@ -240,7 +240,7 @@ import java.util.stream.Stream;
|
|||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* class Qsort {
|
* class Qsort {
|
||||||
* static int qsortCompare(MemorySegment elem1, MemorySegmet elem2) {
|
* static int qsortCompare(MemorySegment elem1, MemorySegment elem2) {
|
||||||
* return Integer.compare(elem1.get(JAVA_INT, 0), elem2.get(JAVA_INT, 0));
|
* return Integer.compare(elem1.get(JAVA_INT, 0), elem2.get(JAVA_INT, 0));
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
@ -268,7 +268,7 @@ import java.util.stream.Stream;
|
|||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* try (Arena arena = Arena.ofConfined()) {
|
* try (Arena arena = Arena.ofConfined()) {
|
||||||
* MemorySegment comparFunc = linker.upcallStub(comparHandle, comparDesc, arena);
|
* MemorySegment comparFunc = linker.upcallStub(comparHandle, comparDesc, arena);
|
||||||
* MemorySegment array = session.allocateArray(0, 9, 3, 4, 6, 5, 1, 8, 2, 7);
|
* MemorySegment array = arena.allocateArray(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7);
|
||||||
* qsort.invokeExact(array, 10L, 4L, comparFunc);
|
* qsort.invokeExact(array, 10L, 4L, comparFunc);
|
||||||
* int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
|
* int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
|
||||||
* }
|
* }
|
||||||
@ -307,12 +307,12 @@ import java.util.stream.Stream;
|
|||||||
* Linker linker = Linker.nativeLinker();
|
* Linker linker = Linker.nativeLinker();
|
||||||
*
|
*
|
||||||
* MethodHandle malloc = linker.downcallHandle(
|
* MethodHandle malloc = linker.downcallHandle(
|
||||||
* linker.defaultLookup().find("malloc").get(),
|
* linker.defaultLookup().find("malloc").orElseThrow(),
|
||||||
* FunctionDescriptor.of(ADDRESS, JAVA_LONG)
|
* FunctionDescriptor.of(ADDRESS, JAVA_LONG)
|
||||||
* );
|
* );
|
||||||
*
|
*
|
||||||
* MethodHandle free = linker.downcallHandle(
|
* MethodHandle free = linker.downcallHandle(
|
||||||
* linker.defaultLookup().find("free").get(),
|
* linker.defaultLookup().find("free").orElseThrow(),
|
||||||
* FunctionDescriptor.ofVoid(ADDRESS)
|
* FunctionDescriptor.ofVoid(ADDRESS)
|
||||||
* );
|
* );
|
||||||
* }
|
* }
|
||||||
@ -334,9 +334,15 @@ import java.util.stream.Stream;
|
|||||||
* method, as follows:
|
* method, as follows:
|
||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* MemorySegment allocateMemory(long byteSize, Arena arena) {
|
* MemorySegment allocateMemory(long byteSize, Arena arena) throws Throwable {
|
||||||
* MemorySegment segment = (MemorySegment)malloc.invokeExact(byteSize); // size = 0, scope = always alive
|
* MemorySegment segment = (MemorySegment) malloc.invokeExact(byteSize); // size = 0, scope = always alive
|
||||||
* return segment.reinterpret(byteSize, arena, s -> free.invokeExact(s)); // size = byteSize, scope = arena.scope()
|
* return segment.reinterpret(byteSize, arena, s -> {
|
||||||
|
* try {
|
||||||
|
* free.invokeExact(s);
|
||||||
|
* } catch (Throwable e) {
|
||||||
|
* throw new RuntimeException(e);
|
||||||
|
* }
|
||||||
|
* }); // size = byteSize, scope = arena.scope()
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
@ -389,7 +395,7 @@ import java.util.stream.Stream;
|
|||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* Linker linker = Linker.nativeLinker();
|
* Linker linker = Linker.nativeLinker();
|
||||||
* MethodHandle printf = linker.downcallHandle(
|
* MethodHandle printf = linker.downcallHandle(
|
||||||
* linker.defaultLookup().lookup("printf").get(),
|
* linker.defaultLookup().find("printf").orElseThrow(),
|
||||||
* FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT),
|
* FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT),
|
||||||
* Linker.Option.firstVariadicArg(1) // first int is variadic
|
* Linker.Option.firstVariadicArg(1) // first int is variadic
|
||||||
* );
|
* );
|
||||||
@ -616,12 +622,12 @@ public sealed interface Linker permits AbstractLinker {
|
|||||||
* Linker.Option ccs = Linker.Option.captureCallState("errno");
|
* Linker.Option ccs = Linker.Option.captureCallState("errno");
|
||||||
* MethodHandle handle = Linker.nativeLinker().downcallHandle(targetAddress, FunctionDescriptor.ofVoid(), ccs);
|
* MethodHandle handle = Linker.nativeLinker().downcallHandle(targetAddress, FunctionDescriptor.ofVoid(), ccs);
|
||||||
*
|
*
|
||||||
* StructLayout capturedStateLayout = Linker.Option.capturedStateLayout();
|
* StructLayout capturedStateLayout = Linker.Option.captureStateLayout();
|
||||||
* VarHandle errnoHandle = capturedStateLayout.varHandle(PathElement.groupElement("errno"));
|
* VarHandle errnoHandle = capturedStateLayout.varHandle(PathElement.groupElement("errno"));
|
||||||
* try (Arena arena = Arena.ofConfined()) {
|
* try (Arena arena = Arena.ofConfined()) {
|
||||||
* MemorySegment capturedState = arena.allocate(capturedStateLayout);
|
* MemorySegment capturedState = arena.allocate(capturedStateLayout);
|
||||||
* handle.invoke(capturedState);
|
* handle.invoke(capturedState);
|
||||||
* int errno = errnoHandle.get(capturedState);
|
* int errno = (int) errnoHandle.get(capturedState);
|
||||||
* // use errno
|
* // use errno
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
|
@ -660,20 +660,20 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||||||
* padding layout} elements. As such, the following struct layout creation will fail with an exception:
|
* padding layout} elements. As such, the following struct layout creation will fail with an exception:
|
||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* structLayout(JAVA_SHORT, JAVA_INT)
|
* structLayout(JAVA_SHORT, JAVA_INT);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* To avoid the exception, clients can either insert additional padding layout elements:
|
* To avoid the exception, clients can either insert additional padding layout elements:
|
||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* structLayout(JAVA_SHORT, MemoryLayout.ofPadding(2), JAVA_INT)
|
* structLayout(JAVA_SHORT, MemoryLayout.paddingLayout(2), JAVA_INT);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* Or, alternatively, they can use a member layout which features a smaller alignment constraint. This will result
|
* Or, alternatively, they can use a member layout which features a smaller alignment constraint. This will result
|
||||||
* in a <em>packed</em> struct layout:
|
* in a <em>packed</em> struct layout:
|
||||||
*
|
*
|
||||||
* {@snippet lang = java:
|
* {@snippet lang = java:
|
||||||
* structLayout(JAVA_SHORT, JAVA_INT.withByteAlignment(2))
|
* structLayout(JAVA_SHORT, JAVA_INT.withByteAlignment(2));
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
static StructLayout structLayout(MemoryLayout... elements) {
|
static StructLayout structLayout(MemoryLayout... elements) {
|
||||||
|
@ -142,7 +142,7 @@ import jdk.internal.vm.annotation.ForceInline;
|
|||||||
* MethodType.methodType(long.class, long.class, long.class));
|
* MethodType.methodType(long.class, long.class, long.class));
|
||||||
* intHandle = MethodHandles.filterCoordinates(intHandle, 1,
|
* intHandle = MethodHandles.filterCoordinates(intHandle, 1,
|
||||||
* MethodHandles.insertArguments(multiplyExact, 0, 4L));
|
* MethodHandles.insertArguments(multiplyExact, 0, 4L));
|
||||||
* intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12
|
* int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* Alternatively, complex var handles can can be obtained
|
* Alternatively, complex var handles can can be obtained
|
||||||
@ -152,7 +152,7 @@ import jdk.internal.vm.annotation.ForceInline;
|
|||||||
* {@snippet lang=java :
|
* {@snippet lang=java :
|
||||||
* MemorySegment segment = ...
|
* MemorySegment segment = ...
|
||||||
* VarHandle intHandle = ValueLayout.JAVA_INT.arrayElementVarHandle();
|
* VarHandle intHandle = ValueLayout.JAVA_INT.arrayElementVarHandle();
|
||||||
* intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12
|
* int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* <h2 id="slicing">Slicing memory segments</h2>
|
* <h2 id="slicing">Slicing memory segments</h2>
|
||||||
@ -756,8 +756,8 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
|||||||
* segment. Equivalent to (but likely more efficient than) the following code:
|
* segment. Equivalent to (but likely more efficient than) the following code:
|
||||||
*
|
*
|
||||||
* {@snippet lang=java :
|
* {@snippet lang=java :
|
||||||
* byteHandle = MemoryLayout.ofSequence(ValueLayout.JAVA_BYTE)
|
* var byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE)
|
||||||
* .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
|
* .varHandle(MemoryLayout.PathElement.sequenceElement());
|
||||||
* for (long l = 0; l < segment.byteSize(); l++) {
|
* for (long l = 0; l < segment.byteSize(); l++) {
|
||||||
* byteHandle.set(segment.address(), l, value);
|
* byteHandle.set(segment.address(), l, value);
|
||||||
* }
|
* }
|
||||||
@ -785,7 +785,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
|||||||
* <p>
|
* <p>
|
||||||
* Calling this method is equivalent to the following code:
|
* Calling this method is equivalent to the following code:
|
||||||
* {@snippet lang=java :
|
* {@snippet lang=java :
|
||||||
* MemorySegment.copy(src, 0, this, 0, src.byteSize);
|
* MemorySegment.copy(src, 0, this, 0, src.byteSize());
|
||||||
* }
|
* }
|
||||||
* @param src the source segment.
|
* @param src the source segment.
|
||||||
* @throws IndexOutOfBoundsException if {@code src.byteSize() > this.byteSize()}.
|
* @throws IndexOutOfBoundsException if {@code src.byteSize() > this.byteSize()}.
|
||||||
|
@ -117,8 +117,8 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||||||
* <p>
|
* <p>
|
||||||
* Consider the following access expressions:
|
* Consider the following access expressions:
|
||||||
* {@snippet lang=java :
|
* {@snippet lang=java :
|
||||||
* int value1 = arrayHandle.get(10, 2, 4); // ok, accessed offset = 8176
|
* int value1 = (int) arrayHandle.get(10, 2, 4); // ok, accessed offset = 8176
|
||||||
* int value2 = arrayHandle.get(0, 0, 30); // out of bounds value for z
|
* int value2 = (int) arrayHandle.get(0, 0, 30); // out of bounds value for z
|
||||||
* }
|
* }
|
||||||
* In the first case, access is well-formed, as the values for {@code x}, {@code y} and {@code z} conform to
|
* In the first case, access is well-formed, as the values for {@code x}, {@code y} and {@code z} conform to
|
||||||
* the bounds specified above. In the second case, access fails with {@link IndexOutOfBoundsException},
|
* the bounds specified above. In the second case, access fails with {@link IndexOutOfBoundsException},
|
||||||
|
@ -89,7 +89,7 @@
|
|||||||
* Linker linker = Linker.nativeLinker();
|
* Linker linker = Linker.nativeLinker();
|
||||||
* SymbolLookup stdlib = linker.defaultLookup();
|
* SymbolLookup stdlib = linker.defaultLookup();
|
||||||
* MethodHandle strlen = linker.downcallHandle(
|
* MethodHandle strlen = linker.downcallHandle(
|
||||||
* stdlib.find("strlen").get(),
|
* stdlib.find("strlen").orElseThrow(),
|
||||||
* FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
|
* FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
|
||||||
* );
|
* );
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,679 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package java.lang.foreign.snippets;
|
||||||
|
|
||||||
|
import java.lang.foreign.AddressLayout;
|
||||||
|
import java.lang.foreign.Arena;
|
||||||
|
import java.lang.foreign.FunctionDescriptor;
|
||||||
|
import java.lang.foreign.Linker;
|
||||||
|
import java.lang.foreign.MemoryLayout;
|
||||||
|
import java.lang.foreign.MemorySegment;
|
||||||
|
import java.lang.foreign.SegmentAllocator;
|
||||||
|
import java.lang.foreign.SequenceLayout;
|
||||||
|
import java.lang.foreign.StructLayout;
|
||||||
|
import java.lang.foreign.SymbolLookup;
|
||||||
|
import java.lang.foreign.ValueLayout;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.lang.invoke.VarHandle;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import static java.lang.foreign.MemoryLayout.sequenceLayout;
|
||||||
|
import static java.lang.foreign.MemoryLayout.structLayout;
|
||||||
|
import static java.lang.foreign.SymbolLookup.libraryLookup;
|
||||||
|
import static java.lang.foreign.SymbolLookup.loaderLookup;
|
||||||
|
import static java.lang.foreign.ValueLayout.*;
|
||||||
|
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Snippets for the java.lang.foreign documentation.
|
||||||
|
*/
|
||||||
|
class Snippets {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new snippet.
|
||||||
|
*/
|
||||||
|
public Snippets() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ArenaSnippets {
|
||||||
|
|
||||||
|
void globalArena() {
|
||||||
|
// @start region="global-allocation":
|
||||||
|
MemorySegment segment = Arena.global().allocate(100, 1); // @highlight regex='global()'
|
||||||
|
// ...
|
||||||
|
// segment is never deallocated!
|
||||||
|
// @end
|
||||||
|
}
|
||||||
|
|
||||||
|
void autoArena() {
|
||||||
|
// @start region="auto-allocation":
|
||||||
|
MemorySegment segment = Arena.ofAuto().allocate(100, 1); // @highlight regex='ofAuto()'
|
||||||
|
// ...
|
||||||
|
segment = null; // the segment region becomes available for deallocation after this point
|
||||||
|
// @end
|
||||||
|
}
|
||||||
|
|
||||||
|
void confinedArena() {
|
||||||
|
// @start region="confined-allocation":
|
||||||
|
MemorySegment segment = null;
|
||||||
|
try (Arena arena = Arena.ofConfined()) { // @highlight regex='ofConfined()'
|
||||||
|
segment = arena.allocate(100);
|
||||||
|
// ...
|
||||||
|
} // segment region deallocated here
|
||||||
|
segment.get(ValueLayout.JAVA_BYTE, 0); // throws IllegalStateException
|
||||||
|
// @end
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
// @start region="slicing-arena":
|
||||||
|
class SlicingArena implements Arena {
|
||||||
|
final Arena arena = Arena.ofConfined();
|
||||||
|
final SegmentAllocator slicingAllocator;
|
||||||
|
|
||||||
|
SlicingArena(long size) {
|
||||||
|
slicingAllocator = SegmentAllocator.slicingAllocator(arena.allocate(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemorySegment allocate(long byteSize, long byteAlignment) {
|
||||||
|
return slicingAllocator.allocate(byteSize, byteAlignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemorySegment.Scope scope() {
|
||||||
|
return arena.scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
arena.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// @end
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// @start region="slicing-arena-main":
|
||||||
|
try (Arena slicingArena = new SlicingArena(1000)) {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
MemorySegment s = slicingArena.allocateArray(JAVA_INT, 1, 2, 3, 4, 5);
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
} // all memory allocated is released here
|
||||||
|
// @end
|
||||||
|
}
|
||||||
|
|
||||||
|
void arenaOverlap() {
|
||||||
|
try (var arena = Arena.ofConfined()) {
|
||||||
|
var S1 = arena.allocate(16L);
|
||||||
|
var S2 = arena.allocate(16L);
|
||||||
|
|
||||||
|
if (
|
||||||
|
// @start region="arena-overlap":
|
||||||
|
S1.asOverlappingSlice(S2).isEmpty() == true
|
||||||
|
// @end
|
||||||
|
) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class AddressLayoutSnippets {
|
||||||
|
void withTargetLayout() {
|
||||||
|
AddressLayout addressLayout = ADDRESS;
|
||||||
|
AddressLayout unboundedLayout = addressLayout.withTargetLayout(
|
||||||
|
sequenceLayout(ValueLayout.JAVA_BYTE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FunctionDescriptionSnippets {
|
||||||
|
}
|
||||||
|
|
||||||
|
static class GroupLayoutSnippets {
|
||||||
|
}
|
||||||
|
|
||||||
|
static class LinkerSnippets {
|
||||||
|
|
||||||
|
void downcall() throws Throwable {
|
||||||
|
Linker linker = Linker.nativeLinker();
|
||||||
|
MethodHandle strlen = linker.downcallHandle(
|
||||||
|
linker.defaultLookup().find("strlen").orElseThrow(),
|
||||||
|
FunctionDescriptor.of(JAVA_LONG, ADDRESS)
|
||||||
|
);
|
||||||
|
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
MemorySegment str = arena.allocateUtf8String("Hello");
|
||||||
|
long len = (long) strlen.invokeExact(str); // 5
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void qsort() throws Throwable {
|
||||||
|
Linker linker = Linker.nativeLinker();
|
||||||
|
MethodHandle qsort = linker.downcallHandle(
|
||||||
|
linker.defaultLookup().find("qsort").orElseThrow(),
|
||||||
|
FunctionDescriptor.ofVoid(ADDRESS, JAVA_LONG, JAVA_LONG, ADDRESS)
|
||||||
|
);
|
||||||
|
|
||||||
|
class Qsort {
|
||||||
|
static int qsortCompare(MemorySegment elem1, MemorySegment elem2) {
|
||||||
|
return Integer.compare(elem1.get(JAVA_INT, 0), elem2.get(JAVA_INT, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionDescriptor compareDesc = FunctionDescriptor.of(JAVA_INT,
|
||||||
|
ADDRESS.withTargetLayout(JAVA_INT),
|
||||||
|
ADDRESS.withTargetLayout(JAVA_INT));
|
||||||
|
MethodHandle compareHandle = MethodHandles.lookup()
|
||||||
|
.findStatic(Qsort.class, "qsortCompare",
|
||||||
|
compareDesc.toMethodType());
|
||||||
|
|
||||||
|
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
MemorySegment compareFunc = linker.upcallStub(compareHandle, compareDesc, arena);
|
||||||
|
MemorySegment array = arena.allocateArray(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7);
|
||||||
|
qsort.invokeExact(array, 10L, 4L, compareFunc);
|
||||||
|
int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void returnPointer() throws Throwable {
|
||||||
|
Linker linker = Linker.nativeLinker();
|
||||||
|
|
||||||
|
MethodHandle malloc = linker.downcallHandle(
|
||||||
|
linker.defaultLookup().find("malloc").orElseThrow(),
|
||||||
|
FunctionDescriptor.of(ADDRESS, JAVA_LONG)
|
||||||
|
);
|
||||||
|
|
||||||
|
MethodHandle free = linker.downcallHandle(
|
||||||
|
linker.defaultLookup().find("free").orElseThrow(),
|
||||||
|
FunctionDescriptor.ofVoid(ADDRESS)
|
||||||
|
);
|
||||||
|
|
||||||
|
MemorySegment segment = (MemorySegment) malloc.invokeExact(100);
|
||||||
|
|
||||||
|
class AllocateMemory {
|
||||||
|
|
||||||
|
MemorySegment allocateMemory(long byteSize, Arena arena) throws Throwable {
|
||||||
|
MemorySegment segment = (MemorySegment) malloc.invokeExact(byteSize); // size = 0, scope = always alive
|
||||||
|
return segment.reinterpret(byteSize, arena, s -> {
|
||||||
|
try {
|
||||||
|
free.invokeExact(s);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}); // size = byteSize, scope = arena.scope()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AllocateMemory2 {
|
||||||
|
|
||||||
|
MemorySegment allocateMemory(long byteSize, Arena arena) {
|
||||||
|
MemorySegment segment = trySupplier(() -> (MemorySegment) malloc.invokeExact(byteSize)); // size = 0, scope = always alive
|
||||||
|
return segment.reinterpret(byteSize, arena, s -> trySupplier(() -> free.invokeExact(s))); // size = byteSize, scope = arena.scope()
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
interface ThrowingSupplier<T> {
|
||||||
|
T get() throws Throwable;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
<T> T trySupplier(ThrowingSupplier<? extends T> supplier) {
|
||||||
|
try {
|
||||||
|
return supplier.get();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new RuntimeException(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AllocateMemory3 {
|
||||||
|
|
||||||
|
MemorySegment allocateMemory(long byteSize, Arena arena) throws Throwable {
|
||||||
|
MemorySegment segment = (MemorySegment) malloc.invokeExact(byteSize); // size = 0, scope = always alive
|
||||||
|
return segment.reinterpret(byteSize, arena, this::freeMemory); // size = byteSize, scope = arena.scope()
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeMemory(MemorySegment segment) {
|
||||||
|
try {
|
||||||
|
free.invokeExact(segment);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void variadicFunc() throws Throwable {
|
||||||
|
|
||||||
|
Linker linker = Linker.nativeLinker();
|
||||||
|
MethodHandle printf = linker.downcallHandle(
|
||||||
|
linker.defaultLookup().find("printf").orElseThrow(),
|
||||||
|
FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT),
|
||||||
|
Linker.Option.firstVariadicArg(1) // first int is variadic
|
||||||
|
);
|
||||||
|
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
int res = (int) printf.invokeExact(arena.allocateUtf8String("%d plus %d equals %d"), 2, 2, 4); //prints "2 plus 2 equals 4"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void downcallHandle() {
|
||||||
|
Linker linker = Linker.nativeLinker();
|
||||||
|
FunctionDescriptor function = null;
|
||||||
|
MemorySegment symbol = null;
|
||||||
|
|
||||||
|
linker.downcallHandle(function).bindTo(symbol);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void captureCallState() throws Throwable {
|
||||||
|
|
||||||
|
MemorySegment targetAddress = null; // ...
|
||||||
|
Linker.Option ccs = Linker.Option.captureCallState("errno");
|
||||||
|
MethodHandle handle = Linker.nativeLinker().downcallHandle(targetAddress, FunctionDescriptor.ofVoid(), ccs);
|
||||||
|
|
||||||
|
StructLayout capturedStateLayout = Linker.Option.captureStateLayout();
|
||||||
|
VarHandle errnoHandle = capturedStateLayout.varHandle(PathElement.groupElement("errno"));
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
MemorySegment capturedState = arena.allocate(capturedStateLayout);
|
||||||
|
handle.invoke(capturedState);
|
||||||
|
int errno = (int) errnoHandle.get(capturedState);
|
||||||
|
// use errno
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void captureStateLayout() {
|
||||||
|
String capturedNames = Linker.Option.captureStateLayout().memberLayouts().stream()
|
||||||
|
.map(MemoryLayout::name)
|
||||||
|
.flatMap(Optional::stream)
|
||||||
|
.map(Objects::toString)
|
||||||
|
.collect(Collectors.joining(", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MemoryLayoutSnippets {
|
||||||
|
|
||||||
|
void header() throws Throwable {
|
||||||
|
SequenceLayout taggedValues = sequenceLayout(5,
|
||||||
|
structLayout(
|
||||||
|
ValueLayout.JAVA_BYTE.withName("kind"),
|
||||||
|
MemoryLayout.paddingLayout(24),
|
||||||
|
ValueLayout.JAVA_INT.withName("value")
|
||||||
|
)
|
||||||
|
).withName("TaggedValues");
|
||||||
|
|
||||||
|
long valueOffset = taggedValues.byteOffset(PathElement.sequenceElement(0),
|
||||||
|
PathElement.groupElement("value")); // yields 4
|
||||||
|
|
||||||
|
MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
|
||||||
|
PathElement.groupElement("value"));
|
||||||
|
|
||||||
|
VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
|
||||||
|
PathElement.groupElement("value"));
|
||||||
|
|
||||||
|
MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
|
||||||
|
PathElement.groupElement("kind"));
|
||||||
|
long offset1 = (long) offsetHandle.invokeExact(1L); // 8
|
||||||
|
long offset2 = (long) offsetHandle.invokeExact(2L); // 16
|
||||||
|
}
|
||||||
|
|
||||||
|
void sliceHandle() {
|
||||||
|
MemorySegment segment = null;
|
||||||
|
long offset = 0;
|
||||||
|
MemoryLayout layout = null;
|
||||||
|
|
||||||
|
segment.asSlice(offset, layout.byteSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void sequenceLayout0() {
|
||||||
|
MemoryLayout elementLayout = JAVA_INT;
|
||||||
|
|
||||||
|
sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void structLayout0() {
|
||||||
|
MemoryLayout elementLayout = JAVA_INT;
|
||||||
|
|
||||||
|
structLayout(JAVA_SHORT, JAVA_INT);
|
||||||
|
structLayout(JAVA_SHORT, MemoryLayout.paddingLayout(16), JAVA_INT);
|
||||||
|
structLayout(JAVA_SHORT, JAVA_INT.withByteAlignment(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MemorySegmentSnippets {
|
||||||
|
void header() throws NoSuchMethodException, IllegalAccessException {
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment segment = null; // ...
|
||||||
|
int value = segment.get(ValueLayout.JAVA_INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment segment = null; // ...
|
||||||
|
|
||||||
|
int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment segment = null; // ...
|
||||||
|
|
||||||
|
VarHandle intHandle = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT);
|
||||||
|
MethodHandle multiplyExact = MethodHandles.lookup()
|
||||||
|
.findStatic(Math.class, "multiplyExact",
|
||||||
|
MethodType.methodType(long.class, long.class, long.class));
|
||||||
|
intHandle = MethodHandles.filterCoordinates(intHandle, 1,
|
||||||
|
MethodHandles.insertArguments(multiplyExact, 0, 4L));
|
||||||
|
int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment segment = null; // ...
|
||||||
|
|
||||||
|
VarHandle intHandle = ValueLayout.JAVA_INT.arrayElementVarHandle();
|
||||||
|
int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Arena arena = Arena.ofConfined();
|
||||||
|
MemorySegment segment = arena.allocate(100);
|
||||||
|
MemorySegment slice = segment.asSlice(50, 10);
|
||||||
|
slice.get(ValueLayout.JAVA_INT, 20); // Out of bounds!
|
||||||
|
arena.close();
|
||||||
|
slice.get(ValueLayout.JAVA_INT, 0); // Already closed!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
try (Arena arena = Arena.ofShared()) {
|
||||||
|
SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
|
||||||
|
MemorySegment segment = arena.allocate(SEQUENCE_LAYOUT);
|
||||||
|
int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
|
||||||
|
.mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
|
||||||
|
.sum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
|
||||||
|
byteSegment.get(ValueLayout.JAVA_INT, 0); // fails: layout alignment is 4, segment max alignment is 1
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment longSegment = MemorySegment.ofArray(new long[10]);
|
||||||
|
longSegment.get(ValueLayout.JAVA_INT, 0); // ok: layout alignment is 4, segment max alignment is 8
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
|
||||||
|
byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, 0); // ok: layout alignment is 1, segment max alignment is 1
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment segment = null;
|
||||||
|
long offset = 42;
|
||||||
|
|
||||||
|
MemorySegment z = segment.get(ValueLayout.ADDRESS, offset); // size = 0
|
||||||
|
MemorySegment ptr = z.reinterpret(16); // size = 16
|
||||||
|
int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3); // ok
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment segment = null;
|
||||||
|
long offset = 42;
|
||||||
|
|
||||||
|
MemorySegment ptr = null;
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
MemorySegment z = segment.get(ValueLayout.ADDRESS, offset); // size = 0, scope = always alive
|
||||||
|
ptr = z.reinterpret(16, arena, null); // size = 4, scope = arena.scope()
|
||||||
|
int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3); // ok
|
||||||
|
}
|
||||||
|
int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3); // throws IllegalStateException
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemorySegment segment = null;
|
||||||
|
long offset = 42;
|
||||||
|
|
||||||
|
AddressLayout intArrPtrLayout = ValueLayout.ADDRESS.withTargetLayout(
|
||||||
|
MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT)); // layout for int (*ptr)[4]
|
||||||
|
MemorySegment ptr = segment.get(intArrPtrLayout, offset); // size = 16
|
||||||
|
int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3); // ok
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isAligned(MemorySegment segment, long offset, MemoryLayout layout) {
|
||||||
|
return ((segment.address() + offset) % layout.byteAlignment()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void elements() {
|
||||||
|
MemorySegment segment = null;
|
||||||
|
MemoryLayout elementLayout = JAVA_INT;
|
||||||
|
|
||||||
|
StreamSupport.stream(segment.spliterator(elementLayout), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void asSlice() {
|
||||||
|
MemorySegment segment = null;
|
||||||
|
long offset = 42;
|
||||||
|
MemoryLayout layout = JAVA_INT;
|
||||||
|
|
||||||
|
segment.asSlice(offset, layout.byteSize(), 1);
|
||||||
|
|
||||||
|
segment.asSlice(offset, layout.byteSize(), layout.byteAlignment());
|
||||||
|
|
||||||
|
segment.asSlice(offset, segment.byteSize() - offset);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reinterpret() {
|
||||||
|
MemorySegment segment = null;
|
||||||
|
|
||||||
|
MemorySegment cleanupSegment = MemorySegment.ofAddress(segment.address());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void segmentOffset() {
|
||||||
|
MemorySegment segment = null;
|
||||||
|
MemorySegment other = null;
|
||||||
|
|
||||||
|
long offset = other.address() - segment.address();
|
||||||
|
}
|
||||||
|
|
||||||
|
void fill() {
|
||||||
|
MemorySegment segment = null;
|
||||||
|
byte value = 42;
|
||||||
|
|
||||||
|
var byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE)
|
||||||
|
.varHandle(MemoryLayout.PathElement.sequenceElement());
|
||||||
|
for (long l = 0; l < segment.byteSize(); l++) {
|
||||||
|
byteHandle.set(segment.address(), l, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFrom() {
|
||||||
|
MemorySegment src = null;
|
||||||
|
MemorySegment dst = null;
|
||||||
|
|
||||||
|
// MemorySegment.copy(src, 0, this, 0, src.byteSize());
|
||||||
|
MemorySegment.copy(src, 0, dst, 0, src.byteSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy() {
|
||||||
|
MemorySegment srcSegment = null;
|
||||||
|
long srcOffset = 42;
|
||||||
|
MemorySegment dstSegment = null;
|
||||||
|
long dstOffset = 13;
|
||||||
|
long bytes = 3;
|
||||||
|
|
||||||
|
MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PackageInfoSnippets {
|
||||||
|
|
||||||
|
void header() throws Throwable {
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
MemorySegment segment = arena.allocate(10 * 4);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Linker linker = Linker.nativeLinker();
|
||||||
|
SymbolLookup stdlib = linker.defaultLookup();
|
||||||
|
MethodHandle strlen = linker.downcallHandle(
|
||||||
|
stdlib.find("strlen").orElseThrow(),
|
||||||
|
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
|
||||||
|
);
|
||||||
|
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
MemorySegment cString = arena.allocateUtf8String("Hello");
|
||||||
|
long len = (long) strlen.invokeExact(cString); // 5
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PaddingLayoutSnippets {
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SegmentAllocatorSnippets {
|
||||||
|
void prefixAllocator() {
|
||||||
|
MemorySegment segment = null; //...
|
||||||
|
SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SequenceLayoutSnippets {
|
||||||
|
void header() {
|
||||||
|
MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
|
||||||
|
|
||||||
|
MemoryLayout.structLayout(
|
||||||
|
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||||
|
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||||
|
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reshape() {
|
||||||
|
var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
|
||||||
|
var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT));
|
||||||
|
|
||||||
|
var reshapeSeqImplicit1 = seq.reshape(-1, 6);
|
||||||
|
var reshapeSeqImplicit2 = seq.reshape(2, -1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void flatten() {
|
||||||
|
var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
|
||||||
|
var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class StructLayoutSnippets {
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SymbolLookupSnippets {
|
||||||
|
|
||||||
|
void header() {
|
||||||
|
try (Arena arena = Arena.ofConfined()) {
|
||||||
|
SymbolLookup libGL = libraryLookup("libGL.so", arena); // libGL.so loaded here
|
||||||
|
MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
|
||||||
|
// ...
|
||||||
|
} // libGL.so unloaded here
|
||||||
|
|
||||||
|
System.loadLibrary("GL"); // libGL.so loaded here
|
||||||
|
// ...
|
||||||
|
SymbolLookup libGL = loaderLookup();
|
||||||
|
MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
|
||||||
|
|
||||||
|
|
||||||
|
Arena arena = Arena.ofAuto();
|
||||||
|
|
||||||
|
|
||||||
|
libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
|
||||||
|
loaderLookup().find("glGetString").isPresent(); // false
|
||||||
|
|
||||||
|
libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
|
||||||
|
loaderLookup().find("glGetString").isPresent(); // false
|
||||||
|
|
||||||
|
Linker nativeLinker = Linker.nativeLinker();
|
||||||
|
SymbolLookup stdlib = nativeLinker.defaultLookup();
|
||||||
|
MemorySegment malloc = stdlib.find("malloc").orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class UnionLayoutSnippets {
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ValueLayoutSnippets {
|
||||||
|
|
||||||
|
void arrayElementVarHandle() {
|
||||||
|
VarHandle arrayHandle = ValueLayout.JAVA_INT.arrayElementVarHandle(10, 20);
|
||||||
|
|
||||||
|
SequenceLayout arrayLayout = MemoryLayout.sequenceLayout(
|
||||||
|
MemoryLayout.sequenceLayout(10,
|
||||||
|
MemoryLayout.sequenceLayout(20, ValueLayout.JAVA_INT)));
|
||||||
|
|
||||||
|
int value1 = (int) arrayHandle.get(10, 2, 4); // ok, accessed offset = 8176
|
||||||
|
int value2 = (int) arrayHandle.get(0, 0, 30); // out of bounds value for z
|
||||||
|
}
|
||||||
|
|
||||||
|
void statics() {
|
||||||
|
ADDRESS.withByteAlignment(1);
|
||||||
|
JAVA_CHAR.withByteAlignment(1);
|
||||||
|
JAVA_SHORT.withByteAlignment(1);
|
||||||
|
JAVA_INT.withByteAlignment(1);
|
||||||
|
JAVA_LONG.withByteAlignment(1);
|
||||||
|
JAVA_FLOAT.withByteAlignment(1);
|
||||||
|
JAVA_DOUBLE.withByteAlignment(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user